Devon Burley
Devon Burley

Reputation: 65

Setting state without a removed item

I have a todo list here using react and firebase. I can successfully remove an item from firebase and add one also. The problem is getting react to re-render after the item has been removed. I was playing around with it and I realize what I'm doing wrong but don't know how to solve my problem.

Here is my componentDidMount method where I set the state to equal the data firebase sends.

componentDidMount() {
  this.todosRef.on('child_added', snapshot => {
    const todo = { key: snapshot.key, value: snapshot.val() }
    this.setState({ todos: this.state.todos.concat( todo ) });
  });

  this.todosRef.on('child_removed', snapshot => {
    const removedTodo = { key: snapshot.key, value: snapshot.val() }
    const index = this.state.todos.indexOf(removedTodo);
    this.setState({ todos: this.state.todos.splice(index, removedTodo) 
    });
  });
}

As you can see whenever I delete a item and call this.setState({ todos: this.state.todos.splice(index, removedTodo) }); it sets the state to be an empty array (because I'm trying to set the state to the item I just deleted...) which re-renders the page and shows nothing. I would like it to re-render the page and still have the remaining todos.

Upvotes: 2

Views: 47

Answers (2)

Tholle
Tholle

Reputation: 112897

indexOf will just look for the object with the exact same object reference, so even if you create a new object with the exact same data as the todo you want to remove it will not work, sadly.

You could instead filter out the item with the same key as snapshot.key.

this.todosRef.on('child_removed', snapshot => {
  this.setState(previousState => {
    const todos = previousState.todos.filter(todo => todo.key !== snapshot.key);

    return { todos };
  });
});

Upvotes: 3

Sushanth --
Sushanth --

Reputation: 55750

Splice returns the deleted elements if any. Since in your example you are mutating the array, the new state will be set to the array containing the deleted element.

this.state.todos.splice(index, removedTodo);

is supposed to be

this.state.todos.splice(index, 1);

And this should be performed before setting the state.

this.todosRef.on('child_removed', snapshot => {
  const removedTodo = {
    key: snapshot.key,
    value: snapshot.val()
  }
  const index = this.state.todos.indexOf(removedTodo);

  let todos = this.state.todos.splice(index, removedTodo);
  todos.splice(index, 1);

  this.setState({
    todos: todos
  });
});

Upvotes: 2

Related Questions