Reputation: 3968
My code looks something like this:
const countersSelector = () => (store) => store.counters;
const MethodOne = () => {
// Method: Object destructuring
const counters = useSelector(countersSelector);
console.log("render MethodOne");
useEffect(() => {
console.log("in useeffect methodone");
}, [counters]);
return (
<div>
<p>{`firstCounter: ${counters}`}</p>
<p>{`renders: ${renderCount}`}</p>
</div>
);
};
export default MethodOne;
This is the full app: https://codesandbox.io/s/redux-useselector-object-destructuring-example-forked-1m87x
And every time counters
object is changed (not its value, but the object reference itself), that useEffect()
gets triggered.
Can i memoize it somehow, so that counters
will only change if the actual values of store.counters
change?
Upvotes: 1
Views: 546
Reputation: 67469
I'm not sure what you're asking for here.
state.counters
changing to a new object reference is how immutable updates work. Immutable updates always require updating _all nested fields. So, if the action is supposed to update rootState.counters.firstCounter
, it requires creating a new object for counters
and a new object for rootState
.
So, if your selector is state => state.counters
, then useSelector
will re-render the component every time the counters
object changes to a new reference, useEffect
will re-run because there is a new reference inside its dependencies array, and that is exactly how this is supposed to work.
As a side note, your countersSelector
is incorrect. It's written as a "factory function" that returns a selector. That means that useSelector
will actually be looking at the new function reference, not the value extracted from state.
Instead, it should just be state => state.counters
.
Upvotes: 2