2

I'm practicing react, and just now I'm about to make a to-do list. While i was working. I wanted to test my code with console.log to see input values are passing correctly to state. However for awhile I was confused to see how console.log would always output the previous state. Until later, i just embeded <p>{this.state.myArray}</p> and it shows it is working correctly. I presume this.setState({ myArray: this.state.message }); is still finishing executing while console.log already executed.

I'm pretty sure im using console.log the wrong way to test code. New programmer here.

class ToDoInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.state = { message: "", myArray: "" };
  }

  handleChange(e) {
    this.setState({ message: e.target.value });
    console.log("handleChange: " + this.state.message); //testing
  }

  handleSubmit(e) {
    this.setState({ myArray: this.state.message });
    console.log("handleSubmit: " + this.state.myArray); //testing
  }

  render() {
    return (
      <form>
        <input
          type="text"
          value={this.state.content}
          onChange={this.handleChange}
        />
        <input type="button" value="submit" onClick={this.handleSubmit} />
        <p>{this.state.myArray}</p>
      </form>
    );
  }
}

codeSandBox link

2
  • 1
    State changes are asychronous. Try passing a callback as the second argument to this.setState, the console log in there Commented Jan 31, 2020 at 22:22
  • 1
    As @evolutionxbox suggests, try this.setState({message: e.target.value}, () => {console.log(this.state.message);}); Commented Jan 31, 2020 at 22:30

1 Answer 1

1

The problem you're running into is that setState is asynchronous and that it does not set the state immediately but after a short delay. There are several reasons that React does this, but one of them is that it allows React to group multiple state changes and then rerender your component a single time, instead of re-rendering every time setState is called.

If you want to use the state after setting the state, you can use the second argument of setState like this:

  handleSubmit(e) {
    this.setState({ myArray: this.state.message }, () => {
      console.log("handleSubmit: " + this.state.myArray);
    });
  }

You can read more about setState is asynchronous here. Although that Github issue is probably more in-depth than you're looking for.

In your example above, it might be worth putting the console.log(this.state) within your render function, as that should always have the most up-to-date state.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.