Reputation: 60
This is a simple TO-DO app in react in which App.js
takes data from TodosData.js
and the list is shown with the component TodoItem.js
. Now the checkboxes and data can be viewed when rendered. But when I click on the checkbox it doesn't work. I tried console logging handleChange
function which seems to work. It seems like there maybe problems inside the handleChange
function which I can't figure out.
I am following a freecodecamp tutorial on YT and I also checked it several times but can't find the problem here.
App.js code:
import React from 'react';
import TodoItem from './TodoItem'
import todosData from './todosData'
class App extends React.Component {
constructor() {
super ()
this.state = { todos: todosData }
this.handleChange = this.handleChange.bind(this)
}
handleChange(id) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})
return {
todos: updatedTodos
}
})
}
render() {
const todoItems = this.state.todos.map(itemEach => <TodoItem key = {itemEach.id} itemEach = {itemEach}
handleChange = {this.handleChange} />)
return (
<div className = "todo-list">
{todoItems}
</div>
)
}
}
export default App;
TodoItem.js code:
import React from 'react';
function TodoItem(props) {
return(
<div className = "todo-item">
<input type = "checkbox"
checked={props.itemEach.completed}
onChange={() => props.handleChange(props.itemEach.id)}
/>
<p>{props.itemEach.text}</p>
</div>
)
}
export default TodoItem
TodosData.js code:
const todosData = [
{
id: 1,
text: "Take out the trash",
completed: true
},
{
id: 2,
text: "Grocery shopping",
completed: false
},
{
id: 3,
text: "Clearn gecko tank",
completed: false
},
{
id: 4,
text: "Mow lawn",
completed: true
},
{
id: 5,
text: "Catch up on Arrested Development",
completed: false
}
]
export default todosData
Is there a better way to implement this? This way of doing checkbox seems quite complicated for a beginner like myself. Also how can I improve this code?
Upvotes: 0
Views: 99
Reputation: 7911
You are mutating the state in your handleChange
function. Hence it gets the prevState
twice. Once for the original previous state, next for the update that you make inside the handleChange
.
You can probably lose the reference, by spreading the todo
from state like this.
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
const resTodo = { ...todo };
if (todo.id === id) {
resTodo.completed = !resTodo.completed;
}
return resTodo;
});
return {
todos: updatedTodos
};
});
Here's a working codesandbox
Upvotes: 1