How To Avoid Rerender All Child Components Which In Loop When Parent Component State Update
Solution 1:
for that you can use React.memo that will memoize your component if props remains the same. But given your code you need to make some extra changes:
you have to apply
useCallback
to memoize onChangeHandle function;to memoize properly onChangeHandle you need to refactor it. you can't pass
selectedChild
directly, otherwise it memoizes its value. usesetSelectedChild
passing as argument a function that takesselectedChild
instead.your Child should receive
isSelected
as boolean value instead of function. otherwise props will remain the same and Child never updates;importReact, { useState, memo, useCallback } from"react"; functionParent() { const [selectedChild, setSelectedChild] = useState([]); const onChangeHandle = useCallback((event, id) => { setSelectedChild(selectedChild => { const checked = event.target.checked; let updatedArray = [...selectedChild]; if (checked) { if (!selectedChild.includes(id)) { updatedArray.push(id); } } else { var index = updatedArray.indexOf(id); if (index !== -1) { updatedArray.splice(index, 1); } } return updatedArray; }); }, []); constdummy = id => { return selectedChild.includes(id); }; constrenderChildren = () => [1, 2, 3].map((value, index) => { return ( <Childkey={index}index={index}value={value}handle={onChangeHandle}isSelected={dummy(index)} /> ); }); return ( <div><table><tbody>{renderChildren()}</tbody></table><div>{selectedChild}</div></div> ); } constChild = memo(({ index, value, handle, isSelected }) => { console.log("rendering"); return ( <tr><td><inputtype="checkbox"checked={isSelected}onChange={event => handle(event, index)} /> </td><td> hello {index} {value} </td></tr> ); }); exportdefaultfunctionApp() { return ( <divclassName="App"><Parent /></div> ); }
https://stackblitz.com/edit/so-memo-children?file=src/App.js
Solution 2:
The basic answer is use React.memo
on Child
.
constChild = memo(functionChild(...) {...})
But to make memo
work, the component needs to receive the same props if it shouldn't get rerendered. That means using useCallback
on onChangeHandle
:
const onChangeHandle = useCallback((event, id) => {...}, [])
But since onChangeHandle
uses selectedChild
that always changes on checkbox change, you'll also need to ref it using useRef
:
const selectedChildRef = useRef();
selectedChildRef.current = selectedChild;
and use reffed version inside of onChangeHandle
.
The last thing that needs to be done is to change isSelected
prop from function to just a flag since it needs to be run on each checkbox change:
isSelected={selectedChild.includes(index)}
Solution 3:
You could implement shouldComponentUpdate (doc: https://reactjs.org/docs/react-component.html#shouldcomponentupdate) inside the definition of Child to have more control over when it rerenders. But that's only meant for cases where you have performance issues- generally you don't have to worry about it, and letting them all rerender is standard.
Post a Comment for "How To Avoid Rerender All Child Components Which In Loop When Parent Component State Update"