react-ridge-state
react-ridge-state copied to clipboard
Components Re-rendering
Given the following example my understanding is that Component should only re-render when value changes. But it seems that because useSelector internally uses use which uses useState you are essentially subscribing to the entire state update but just returning a filtered value? So Component re-renders whenever anything in state changes? Or have I misunderstood something?
// state.js
export const exampleState = newRidgeState({ count: 0, value: 0 });
setInterval(() => {
// we are only updating the count value
exampleState.set(x => ({...x, count: x.count + 1 }));
}, 100);
// component.js
const Component = ({ children }) => {
console.log("Render: ExampleInner");
// we want to subscribe to only changes to value and only rerender if value changes
const exampleValue = exampleState.useSelector(x => x.value);
return ( ... );
};
The desired behaviour is not re-rendering on state updates when deep value of selector has not changed. It should work!
Hmm yeah this is what I thought but I can't see how this can be achieved. Because in the code the use function is doing:
const [state, setState] = useState();
sub(setState);
So anytime the subscriber fires it is going to cause a re-render.
Here is a code sandbox showing this:
https://codesandbox.io/s/peaceful-http-lk8bx?file=/src/App.js
Shouldn't useSelector subscribe to the state updates directly so it can filter on the value and then setState accordingly? Instead of using the use function?
I've opened a PR that I believe fixes this issue. (Sorry for the confusing account switching 😂 Me and JakeNap are the same person).
https://github.com/web-ridge/react-ridge-state/pull/19
Let me know what you think? I've tested this tweak in the PR and it fixes my issue and I think it's how useSelector should handle state updates. But there maybe some context I'm missing as to why this library doesn't do this already.
@RichardLindhout any thoughts on this?