Tiago Bértolo Tiago Bértolo - 2 months ago 7
React JSX Question

Reactjs is not rendering my state properly

This is my todo app made with ReactJS. I am not able to delete todo's properly.

It always removes the last todo, regardless of the one i click.

Example: If i click to delete 'Buy socks', it will remove 'Oi them'. If i try to check my list state in the debugger, it deleted the correct ToDo.

I uploaded the code to GitHub repository, it was setup with create-react-app should be very easy to setup.

From what i understand the todo entry that i delete in the state of the TodoList does not remove the state of the removed children, and therefore it does not cease to exist.

How do i take care of it? What am i doing wrong?

Hint: here is a gist with unnecessary code removed.

Answer

Right now your deleteTodo function has the wrong this bound to it. The deleteTodo function wants to set the state of the parent component, and calls this.setState(). However, the this is bound in the child's constructor. You want to bind this to the deleteTodo in the constuctor of the parent component: TodoList.

That way when the function is called, it will correctly set the state of TodoList with the new, filtered list of todos.

So be more specific about the changes needed in the code you posted.

First in the constructor of TodoList, bind deleteTodo

this.deleteTodo = this.deleteTodo.bind(this)

Now when this.setState is called in the deleteTodo function it will be setting the state of the correct component.

Now we need to make sure we correctly pass in the argument of delete todo. In the Todo component, replace

onClick={this.props.deleteTodo.bind(this,todoText)}

with

function(){this.props.deleteTodo(todoText)}

You do not need to bind here, wrap the deleteTodo function so that when onClick is called the wrapper function calls deleteTodo with the correct argument.

When the element is clicked, the function assigned to the onClick prop will be called, with a click event object as an argument. We set this function up to call deleteTodo with the correct argument, ignoring the event object.