I tried to boil down the problem into an example as simple as possible:
We have a list of child components, each called NumChoice
, each representing a number. NumChoice
is wrapped in React.memo
. In the parent component, we have an array of booleans, choices
, each corresponding to one of the child components NumChoice
. At first, all the elements of choices
are false
. To render the child components, we iterate through choices
, and for each choice, generate the corresponding child component NumChoice
. We define a function chooseDivisibles
in the parent component, using useCallback
that is called from each child component NumChoice
. chooseDivisibles
takes the index of the NumChoice
who called it and changes the corresponding element of choices
to true
. Each NumChoice
has a "red" background color if its corresponding element in choices
is true
, otherwise, its background color is "white".
The complete code is available at: https://codesandbox.io/s/react-rerender-l4e3c?fontsize=14&hidenavigation=1&theme=dark
Wrapping NumChoice
in React.memo
and chooseDivisibles
in useCallback
, we expected to only rerender NumChoice
components whose corresponding element of choices
changes but React re-renders them all. chooseDivisibles
is wrapped in useCallback
, which lists no dependency other than setChoices
. Also, NumChoice
is wrapped in React.memo
and it should only rerender if the specified props change, but they do not, and changing choices
should not have any effect on rerendering NumChoice
. If we exclude checking the equality of chooseDivisibles
in previous and next props, it works as expected, but I argue that the comparison of previous and next chooseDivisibles
should not affect rerendering NumChoice
because it is wrapped in useCallback
and does not depend on choices
. How can we prevent re-rendering the NumChoice
components whose props
are not changed?
Ah I see that in NumChoice.js
we're also asserting prevProps.chooseDivisibles === nextProps.chooseDivisibles
, which is always false
, since chooseDivisibles={event => chooseDivisibles(idx)}
generates a new function every time
If you remove prevProps.chooseDivisibles === nextProps.chooseDivisibles
, it will only re-render the affected ones!
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