import type { Ref } from 'vue'; import { ref, onBeforeUnmount } from 'vue'; import raf from '../../../_util/raf'; export default function useRaf(callback: Callback) { const rafRef = ref(); const removedRef = ref(false); function trigger(...args: any[]) { if (!removedRef.value) { raf.cancel(rafRef.value); rafRef.value = raf(() => { callback(...args); }); } } onBeforeUnmount(() => { removedRef.value = true; raf.cancel(rafRef.value); }); return trigger; } type Callback = (ori: T) => T; export function useRafState( defaultState: T | (() => T), ): [Ref, (updater: Callback) => void] { const batchRef = ref[]>([]); const state: Ref = ref( typeof defaultState === 'function' ? (defaultState as any)() : defaultState, ); const flushUpdate = useRaf(() => { let value = state.value; batchRef.value.forEach(callback => { value = callback(value); }); batchRef.value = []; state.value = value; }); function updater(callback: Callback) { batchRef.value.push(callback); flushUpdate(); } return [state, updater]; }