Last active
August 9, 2024 22:21
-
-
Save bgmort/97741f3b521c3f7b7491640d1daa8db4 to your computer and use it in GitHub Desktop.
useMemoStable, a useMemo that you can count on to only run once per set of dependency values
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useRef } from 'react' | |
/** | |
* This could also be called `useDerived`. Works like useMemo, | |
* except it guarantees that it only executes once per change of dependency values, | |
* which is what `useMemo` is often expected to do, but doesn't guarantee, and doesn't | |
* do in strict mode. | |
* | |
* Differs from `useEffect` in that the value is computed synchronously during render | |
*/ | |
export function useMemoStable<T> (factory: () => T, deps: any[]) { | |
const valueRef = useRef<T>() | |
const depsRef = useRef<any[]>() | |
if (!deps) throw new Error('useMemoStable: missing dependency array') | |
if (!depsRef.current || !depsEqual(deps, depsRef.current)) { | |
// If dependencies have changed, compute new value and update references | |
valueRef.current = factory() | |
depsRef.current = deps | |
} | |
return valueRef.current as T | |
} | |
function depsEqual (deps: any[], prevDeps: any[]) { | |
if (deps.length !== prevDeps.length) return false | |
for (let i = 0; i < deps.length; i++) { | |
if (deps[i] !== prevDeps[i]) return false | |
} | |
return true | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment