Home > OS >  Why did I need to wrap the state in brackets to assign it to a variable in ReactJs?
Why did I need to wrap the state in brackets to assign it to a variable in ReactJs?

Time:07-14

I was trying to build a simple Todo App with a currentTodo and an array of pastTodos.

I was unable to push currentTodo to pastTodo using this code here.

  handleClick(e) {
    e.preventDefault();
    let pastTodos = this.state.pastTodos;
    pastTodos.push(this.state.currentTodo);
    this.setState({ pastTodos: pastTodos, currentTodo: "" });
  }

and was only able to do by changing this line

let pastTodos = this.state.pastTodos;

to this

let pastTodos = [this.state.pastTodos];

Why would this be? And is this the best way to do this?

Below is all of my code for greater context.

import React from 'react';

class TodoInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentTodo: "", 
      pastTodos: []
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  handleChange(e) {
    e.preventDefault();
    const currentTodo = e.target.value;
    this.setState({ currentTodo: currentTodo})
  }

  handleClick(e) {
    e.preventDefault();
    let pastTodos = [this.state.pastTodos];
    pastTodos.push(this.state.currentTodo);
    this.setState({ pastTodos: pastTodos, currentTodo: "" });
  }

  render () {
    return (
      <div>
        <input onChange={this.handleChange} type="text" value={this.state.currentTodo}/>
        <br></br>
        <button onClick={this.handleClick}> Add Todo </button>
      </div>
    ); 
  }
}

export default TodoInput;

CodePudding user response:

I highly doubt this is "working":

let pastTodos = [this.state.pastTodos];

At the very least, it's probably producing a bug you haven't noticed yet. Because this is creating a new array with only one element, that element being the value of this.state.pastTodos.

For example, look at the initial value of that state:

pastTodos: []

So what are you updating it to? this:

let pastTodos = [[]];

Then you push a value to it, resulting in this:

[[], someValue]

If you perform that operation again, you get this:

[[[], someValue], anotherValue]

This probably isn't the structure you want.


At a high level, you don't want to mutate state in React. Doing this with an array:

let pastTodos = this.state.pastTodos;

Just creates another reference to the same array. And then you mutate that array:

pastTodos.push(this.state.currentTodo);

Instead of creating a reference to the same array, create a new array:

let pastTodos = [...this.state.pastTodos];

This creates a brand new array and uses the spread syntax to populate it with the items of the array in state. Now you're not modifying that state array but rather just modyfing a locally defined array here:

pastTodos.push(this.state.currentTodo);

Then you can use that locally defined array to update state as you currently do.

  • Related