id | title | sidebar_label |
---|---|---|
caveats |
Caveats |
Caveats |
Proxy and state usage tracking may not work 100% as expected. There are some limitations and workarounds.
const state1 = useTrackedState();
const state2 = useTrackedState();
// state1 and state2 is not referentially equal
// even if the underlying state is referentially equal.
You should use useTrackedState
only once in a component
if you need referential equality of objects in the state.
An object referential change doesn't trigger re-render if an property of the object is accessed in previous render
const state = useTrackedState();
const { foo } = state;
return <Child key={foo.id} foo={foo} />;
const Child = React.memo(({ foo }) => {
// ...
};
// if foo doesn't change, Child won't render, so foo.id is only marked as used.
// it won't trigger Child to re-render even if foo is changed.
You need to explicitly notify an object as used in a memoized component.
import { trackMemo } from 'react-tracked';
const Child = React.memo(({ foo }) => {
trackMemo(foo);
// ...
};
const state = useTrackedState();
const dispatch = useUpdate();
dispatch({ type: 'FOO', value: state.foo }); // This may lead unexpected behavior if state.foo is an object
dispatch({ type: 'FOO', value: state.fooStr }); // This is OK if state.fooStr is a string
It's recommended to use primitive values for dispatch
, setState
and others.
In case you need to pass an object itself, here's a workaround.
import { getUntrackedObject } from 'react-tracked';
dispatch({ type: 'FOO', value: getUntrackedObject(state.foo) });