I am using react with redux and redux thunk. I have an action where I am making a network request. With the useSelector I am getting the data from redux store. I have a problem that the component rerenders every time when I dispatch the action. I want that the component only rerenders when data changes. I tried already use shallowEqual as the second argument for useSelector. But it does not work. I have compressed it to minimal example in this sandbox. In the console you can see that the component rerenders with every network request. Here is the codesandbox: https://codesandbox.io/s/useselector-js6j0?file=/src/App.js:885-1294
here is the code:
function LevelThree() {
console.log(`Level three calls: ${++levelThreeCalls}`);
const contextData = useSelector(state => state.data);
console.log(contextData);
const dispatch = useDispatch();
useInterval(() => {
dispatch(updateData());
}, 1000);
return (
<div>
<button onClick={() => dispatch(updateData())}>Change context</button>
{contextData[0].userId}
</div>
);
}
The reason that your component is re-rendering on every update is because you are fetching the data again and updating it in redux store,
Since the reference of data changes, the useSelector
function returns you a new value and re-renders the component.
You can pass a deepEqual
comparison function as a second argument to useSelector
to avoid re-rendering it data hasn't changed
import _ from 'underscore';
...
const contextData = useSelector(state => state.data, _.isEqual);
However, you must carefully use this and measure how frequently your data will be updated otherwise you will add an added calculation in your code which won't even prevent a re-render many times
Working demo
When an action is dispatched, useSelector() will do a reference comparison of the previous selector result value and the current result value. If they are different, the component will be forced to re-render. If they are the same, the component will not re-render
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With