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.