If I have a component:
function MyComponent() {
const state = useState(resetState())
return jsx(state)
}
then I can trigger a state reset by passing a key
to MyComponent
:
<div>
<MyComponent key={'resetStateOnChangingThisString'} />
</div>
If I want to refactor this component into a hook, what is the hooks equivalent of triggering a reset exactly when the key changes?
useEffect
since it should reset before renderinguseMemo
because that doesn't guarantee stabilityI can use a combination of useMemo
with a useRef
to guarantee stability. Is this the best approach or am I missing something simpler?
This is the simplest approach I've found so far:
function useResetOnKeyChange(getInitialState, key) {
const [state, setState] = useState(getInitialState);
const keyRef = useRef();
useMemo(() => {
if (keyRef.current !== key) {
keyRef.current = key;
setState(getInitialState());
}
}, [key, getInitialState]);
return state;
}
or a version without useState
:
function useResetOnKeyChange<T>(
getInitialState: () => T,
key: string
) {
const stateRef = useRef<T | undefined>()
const keyRef = useRef<string | undefined>()
const state = useMemo(() => {
if (keyRef.current !== key) {
keyRef.current = key
stateRef.current = getInitialState()
}
return stateRef.current
}, [key, getInitialState])
return state
}