import { DependencyList, useRef } from 'react' import { isEqualArray } from '@spicy-hooks/utils' /** * Equivalent to `useMemo` but doesn't suffer from the following * (quoting https://reactjs.org/docs/hooks-faq.html#how-to-memoize-calculations): * > **You may rely on useMemo as a performance optimization, not as a semantic guarantee.** * > In the future, React may choose to “forget” some previously memoized values and recalculate * > them on next render, e.g. to free memory for offscreen components. Write your code so that * > it still works without useMemo — and then add it to optimize performance. * * **Note:** You should not blindly replace all usages of `useMemo` with this hook. * The `useGuaranteedMemo` should be used only in scenarios where re-calculating the memoized * value would cause issues. * * @param factory factory to generate the value that is to be memoized * @param deps array of dependencies for the factory (if any of them changes, the memoized value is dropped and a new one is generated) * @typeParam T type of the memoized value * @category Hook */ export function useGuaranteedMemo (factory: () => T, deps: DependencyList): T { const lastDepsRef = useRef() const lastValueRef = useRef() if (!lastDepsRef.current || !isEqualArray(lastDepsRef.current, deps)) { lastValueRef.current = factory() } lastDepsRef.current = deps return lastValueRef.current! }