In state, I have an array of list objects and would like to toggle the displayAddTaskForm. Every time I set state, the list that gets clicked gets rearranged and moves to the front of the lists on the UI. I believe I know why this is happening, just not sure of the solution. When I setState in toggleAddTaskForm, toggledList is first and then the other lists. How do I update the toggledList without changing the order of the lists. Here is the code.
this.state = {
lists: [
{
id: 1,
header: "To Do",
displayAddTaskForm: false,
},
{
id: 2,
header: "Working on It",
displayAddTaskForm: false,
},
{
id: 3,
header: "Taken Care Of",
displayAddTaskForm: false,
}
],
toggleAddTaskForm: (list) => {
const toggledList = {...list, displayAddTaskForm: !list.displayAddTaskForm}
const otherLists = this.state.lists.filter(l => l.id !== list.id)
this.setState({
lists: [toggledList, ...otherLists]
})
},
}
Putting function in the state is not a common thing. I think you need to seperate that function from state.
You can easily toggle items using Array.map() and checking the clicked item id with the item id. This will not change the order of items.
You can use the following code to toggle only one item:
class App extends Component {
constructor() {
super();
this.state = {
lists: [
{
id: 1,
header: "To Do",
displayAddTaskForm: false
},
{
id: 2,
header: "Working on It",
displayAddTaskForm: false
},
{
id: 3,
header: "Taken Care Of",
displayAddTaskForm: false
}
]
};
}
handleClick = id => {
let newList = this.state.lists.map(item => {
if (item.id === id) {
return {
...item,
displayAddTaskForm: !item.displayAddTaskForm
};
} else {
return {
...item,
displayAddTaskForm: false
};
}
});
this.setState({ lists: newList });
};
render() {
return (
<div>
<ul>
{this.state.lists.map(({ id, header, displayAddTaskForm }) => {
return (
<li key={id} onClick={() => this.handleClick(id)}>
{header} - Toggle Value: {displayAddTaskForm ? "true" : "false"}
</li>
);
})}
</ul>
</div>
);
}
}
Playground
Or if you want to be able to toggle every item, you can change the handleClick function like this:
handleClick = id => {
let newList = this.state.lists.map(item => {
if (item.id === id) {
return {
...item,
displayAddTaskForm: !item.displayAddTaskForm
};
} else {
return {
...item
};
}
});
this.setState({ lists: newList });
};
Playground
You could find the index of the list, copy the lists, and insert the modified list into the new lists array at the same index.
toggleAddTaskForm: (list) => {
const toggledList = {...list, displayAddTaskForm: !list.displayAddTaskForm}
const newLists = [...this.state.lists];
newLists[this.state.lists.indexOf(list)] = toggledList;
this.setState({
lists: newLists
})
}
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