Reputation: 55
I made a jsx array react component. This component should change according to the state value, but react does not re-render even when state change and the jsx array changes.
If I display the state using console.log, the state changes and the items (jsx array component) values change, but no re-render occurs.
const Teams = () => {
const [teams, setTeams] = useState([
{
id: "sldkfjsdf",
level: 0,
name: "test1",
children: [{ id: "kjhckjhs", level: 1, name: "test1-1", children: [] }]
},
{ children: [], id: "sdlkfjsdf234", level: 0, name: "test2" }
]);
var items = [];
const deleteNode = id => {
const tmpNodes = teams;
// check level 0
var index = tmpNodes.findIndex(tmpNode => tmpNode.id === id);
if (index >= 0) {
tmpNodes.splice(index, 1);
} else {
// check level 1
tmpNodes.forEach(tmpTeam => {
index = tmpTeam.children.findIndex(child => child.id === id);
if (index >= 0) {
tmpTeam.children.splice(index, 1);
}
});
}
setTeams(tmpNodes);
};
if (teams) {
teams.forEach(team => {
items.push(
<div
onClick={() => {
deleteNode(team.id);
}}
key={team.id}
>
{team.name}
</div>
);
team.children.forEach(child => {
items.push(
<div
onClick={() => {
deleteNode(team.id);
}}
key={child.id}
>
{child.name}
</div>
);
});
});
}
return <>{items}</>;
};
export default Teams;
I expect when I delete node, react re-render "items".
Upvotes: 1
Views: 1059
Reputation: 11760
You are mutating teams
inside deleteNode
.
Even though you are assigning teams
to tempNodes
, this is still the same object reference.
You can quickly fix this by creating a copy of teams
and assigning it to tempNodes
using the spread operator ...
All you need to do is changing
const tmpNodes = teams;
To
// Create a copy of teams as a new array
const tmpNodes = [...teams];
Upvotes: 3