Reputation: 103
I m having one sub child component which is inside a loop of parent component. when one of the sub child components is updating the state of parent component, it is re-rendering the all children since it is loop. How can i avoid the re-render for each iteration. It should update that particular sub child.
import React, { useState } from "react";
function Parent() {
const [selectedChild, setSelectedChild] = useState([]);
const onChangeHandle = (event, id) => {
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);
}
}
setSelectedChild(updatedArray);
};
return (
<div>
<table>
<tbody>
{[1, 2, 3].map((value, index) => {
return (
<Child
key={index}
index={index}
value={value}
handle={onChangeHandle}
isSelected={selectedChild.includes(index)}
/>
);
})}
</tbody>
</table>
<div>{selectedChild}</div>
</div>
);
}
function Child({ index, value, handle, isSelected }) {
console.log("rendering child");
return (
<tr>
<td>
<SubChild
isChecked={isSelected}
onChangeHandle={handle}
index={index}
/>
</td>
<td>
hello {index} {value}
</td>
</tr>
);
}
function SubChild({ isChecked, onChangeHandle, index }) {
console.log("rendering subchild");
return (
<input
type="checkbox"
checked={isChecked}
onChange={(event) => onChangeHandle(event, index)}
/>
);
}
export default function App() {
return (
<div className="App">
<Parent />
</div>
);
}
Current behaviour: In above code, When i m clicking on the checkbox(which is Sub child) in one of the children component, it is updating the parent component state(selectedChild). So the loop is executing and all children(all table rows) are re rendering.
Expected behaviour: Only that particular sub child have to go for re-render (even it should not re-render child)
Demo: https://codesandbox.io/s/reactqa2-0c0md?file=/src/App.js
Little related question: How to avoid rerender all child components which in loop when parent component state update
Upvotes: 1
Views: 170
Reputation: 53884
You should use memoization (useCallback
/React.memo
) and rewrite handle logic with functional updates.
Also, you avoid Child
to render, since you have a new value
after rendering.
// Make a stable callback
const onChangeHandle = useCallback((event, id) => {
setSelectedChild((updatedArray) => {
if (event.target.checked) {
if (!updatedArray.includes(id)) {
return [...updatedArray, id];
}
} else {
return updatedArray.filter((currId) => currId !== id);
}
return updatedArray;
});
}, []);
// Memoize the component
const MemoChild = React.memo(Child);
const MemoSubChild = React.memo(SubChild);
Upvotes: 1