-
I came up with two methods: const useProxySelector = <Proxy extends object, T>(proxy: Proxy, selector: (state: Proxy) => T) => (
useSyncExternalStore(
(syncSub) => subscribe(proxy, syncSub),
() => selector(proxy),
)
);
// Example
useProxySelector(store.ids, ids => ids.selected == id); With derive from valtio/utils type DeriveGet<T> = (get: <R extends object>(proxy: R) => R) => T
const useDerivedSelector = <Proxy extends object, T>(selector: DeriveGet<T>) => {
const derived = useConst(() => derive({ selector }));
return useSyncExternalStore(
(syncSub) => subscribe(derived, syncSub),
() => derived.selector,
);
};
// Example
useDerivedSelector(get => get(store).ids.selected == id); Both work and it has drastically reduced the amount of renderings. But what better way to create a selector? And is the derive really suitable as a fancy selector? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Yes, that approach works. const useSelector = (proxyObject, selector) => {
const [slice, setSlice] = useState(() => selector(proxyObject))
useEffect(() => subscribe(proxyObject, () => setSlice(selector(proxyObject))), [proxyObject])
return slice
} (☝️ It requires If you use uSES, you need to use const useProxySelector = <Proxy extends object, T>(proxy: Proxy, selector: (state: Proxy) => T) => (
useSyncExternalStore(
useCallback((syncSub) => subscribe(proxy, syncSub), [proxy]),
() => selector(proxy),
)
); I don't think the derive version is necessary nor performant. |
Beta Was this translation helpful? Give feedback.
-
Hi @dai-shi, thanks for the amazing library/ies (sent a sponsor thank you). I'm curious if the above method is the latest, and if so, I think it would make sense to add it to the wiki? |
Beta Was this translation helpful? Give feedback.
Yes, that approach works.
See also: https://github.com/pmndrs/valtio/wiki/How-to-avoid-rerenders-manually#subscribe-and-set-local-state-conditionally
(☝️ It requires
selector
to be stable.)If you use uSES, you need to use
useCallback
for stablesubscribe
function.