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> );
}
Advertisement
Answer
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