mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 12:36:57 +00:00
67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import { SetStateAction, atom } from "jotai";
|
|
|
|
export default function atomWithDebounce<T>(
|
|
initialValue: T,
|
|
delayMilliseconds = 500,
|
|
delayOnResetMilliseconds = 500,
|
|
) {
|
|
const prevTimeoutAtom = atom<ReturnType<typeof setTimeout> | undefined>(
|
|
undefined,
|
|
);
|
|
|
|
// DO NOT EXPORT currentValueAtom as using this atom to set state can cause
|
|
// inconsistent state between currentValueAtom and debouncedValueAtom
|
|
const _currentValueAtom = atom(initialValue);
|
|
const isDebouncingAtom = atom(false);
|
|
|
|
const debouncedValueAtom = atom(
|
|
initialValue,
|
|
(get, set, update: SetStateAction<T>) => {
|
|
clearTimeout(get(prevTimeoutAtom));
|
|
|
|
const prevValue = get(_currentValueAtom);
|
|
const nextValue =
|
|
typeof update === "function"
|
|
? (update as (prev: T) => T)(prevValue)
|
|
: update;
|
|
|
|
const onDebounceStart = () => {
|
|
set(_currentValueAtom, nextValue);
|
|
set(isDebouncingAtom, true);
|
|
};
|
|
|
|
const onDebounceEnd = () => {
|
|
set(debouncedValueAtom, nextValue);
|
|
set(isDebouncingAtom, false);
|
|
};
|
|
|
|
onDebounceStart();
|
|
|
|
const nextTimeoutId = setTimeout(
|
|
() => {
|
|
onDebounceEnd();
|
|
},
|
|
nextValue === initialValue
|
|
? delayOnResetMilliseconds
|
|
: delayMilliseconds,
|
|
);
|
|
|
|
// set previous timeout atom in case it needs to get cleared
|
|
set(prevTimeoutAtom, nextTimeoutId);
|
|
},
|
|
);
|
|
|
|
// exported atom setter to clear timeout if needed
|
|
const clearTimeoutAtom = atom(null, (get, set) => {
|
|
clearTimeout(get(prevTimeoutAtom));
|
|
set(isDebouncingAtom, false);
|
|
});
|
|
|
|
return {
|
|
currentValueAtom: atom((get) => get(_currentValueAtom)),
|
|
isDebouncingAtom,
|
|
clearTimeoutAtom,
|
|
debouncedValueAtom,
|
|
};
|
|
}
|