ant-design/components/form/hooks/useFrameState.ts

50 lines
1.2 KiB
TypeScript

import raf from 'rc-util/lib/raf';
import * as React from 'react';
import { useRef } from 'react';
type Updater<ValueType> = (prev?: ValueType) => ValueType;
export default function useFrameState<ValueType>(
defaultValue: ValueType,
): [ValueType, (updater: Updater<ValueType>) => void] {
const [value, setValue] = React.useState(defaultValue);
const frameRef = useRef<number | null>(null);
const batchRef = useRef<Updater<ValueType>[]>([]);
const destroyRef = useRef(false);
React.useEffect(() => {
destroyRef.current = false;
return () => {
destroyRef.current = true;
raf.cancel(frameRef.current!);
frameRef.current = null;
};
}, []);
function setFrameValue(updater: Updater<ValueType>) {
if (destroyRef.current) {
return;
}
if (frameRef.current === null) {
batchRef.current = [];
frameRef.current = raf(() => {
frameRef.current = null;
setValue((prevValue) => {
let current = prevValue;
batchRef.current.forEach((func) => {
current = func(current);
});
return current;
});
});
}
batchRef.current.push(updater);
}
return [value, setFrameValue];
}