Prevent render by zustand
code is based on commit
Context
has unnecessary rerender issue
Initially I was using Context to share states and functions in different components.
1 | // declare |
The code works but has unnecessary rerenders.
For example, whenever state.keystrokes
is changed by another component, the Typing
is rerendered even though not using state.keystrokes
.
This issue is caused by use of useContext
, as long as I use useContext
, every components will be rendered when one of the states is changed in this context by any other components.
use useShallow
in Zustand to prevent unnecessary rerenders
Zustand offers a hook useShallow
to make sure that component only renders when the picked states are shallowly changed.
Zustand use to object.is() compute shallowEqual.
1 | // now, I use zustand and useShallow to ensure in only showTone or memoryMode change |
use effect and useShallow
to update a non-render-ref
useShallow
works pretty well on unnecessary rerenders, but soon I encountered a new problem.
In this situation, I’m using skipSpaceRef
in a closure, and skipSpaceRef
is not relative to UI render.
However if I use useShallow
to get skipSpace
, once the shallowEqual return false, this component will be rendered even though I’m now using skipSpace
for UI render.
1 | const { showTone, memoryMode } = useAppStore( |
Zustand provides a way to track changes of states which are designed not to tigger render.
In this code, I use the subscribe
API to subscribe a state change, and use useEffect to update its ref, it works perfectly to get a notify of a state change and not tigger a render in the component