From 897e7fdfc07a3528c39ab9ba2e43e67e2d34c9ec Mon Sep 17 00:00:00 2001 From: Anton Arnautov Date: Sun, 8 Dec 2024 12:28:59 +0100 Subject: [PATCH] Check individual selected values --- src/store/hooks/useStateStore.ts | 37 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/store/hooks/useStateStore.ts b/src/store/hooks/useStateStore.ts index fab11df11..0dc17c399 100644 --- a/src/store/hooks/useStateStore.ts +++ b/src/store/hooks/useStateStore.ts @@ -7,15 +7,15 @@ const noop = () => {}; export function useStateStore< T extends Record, - O extends Readonly | Readonly> + O extends Readonly | Readonly>, >(store: StateStore, selector: (v: T) => O): O; export function useStateStore< T extends Record, - O extends Readonly | Readonly> + O extends Readonly | Readonly>, >(store: StateStore | undefined, selector: (v: T) => O): O | undefined; export function useStateStore< T extends Record, - O extends Readonly | Readonly> + O extends Readonly | Readonly>, >(store: StateStore | undefined, selector: (v: T) => O) { const wrappedSubscription = useCallback( (onStoreChange: () => void) => { @@ -26,18 +26,35 @@ export function useStateStore< ); const wrappedSnapshot = useMemo(() => { - let cached: [T, O]; + let cachedTuple: [T, O]; + return () => { - const current = store?.getLatestValue(); + const currentValue = store?.getLatestValue(); + + if (!currentValue) return undefined; + + // store value hasn't changed, no need to compare individual values + if (cachedTuple && cachedTuple[0] === currentValue) { + return cachedTuple[1]; + } + + const newlySelected = selector(currentValue); + + // store value changed but selected values wouldn't have to, double-check selected + if (cachedTuple) { + let selectededAreEqualToCached = true; - if (!current) return undefined; + for (const key in cachedTuple[1]) { + if (cachedTuple[1][key] === newlySelected[key]) continue; + selectededAreEqualToCached = false; + break; + } - if (!cached || cached[0] !== current) { - cached = [current, selector(current)]; - return cached[1]; + if (selectededAreEqualToCached) return cachedTuple[1]; } - return cached[1]; + cachedTuple = [currentValue, newlySelected]; + return cachedTuple[1]; }; }, [store, selector]);