Swaathi Kakarla
Swaathi Kakarla

Reputation: 2443

Discrepancies with setting state values in React

I'm starting out React JS and following this little exercise, https://facebook.github.io/react/docs/more-about-refs.html.

It's fairly simple, but I'm facing a huge discrepancy when setting the state value. When I set the state, I view it in the console by doing this: console.log("s: "+this.state.userInput);. And I also display it in the view with {this.state.userInput}. Fairly simple. But not really. The event and the state value always seem to be a letter apart in the console, but it is perfectly displayed in the view. How is that even possible?!

I wanted to query my server whenever the state changes, but the state is always a letter behind. It's so weird. Could someone please explain to me what this is? And how I can avoid it?

Here's the code.

var SearchContainer = React.createClass({
getInitialState: function() {
  return {userInput: ''};
},

handleChange: function(e) {
    console.log("e: "+e.target.value);
    this.setState({userInput: e.target.value});
    console.log("s: "+this.state.userInput);
},

clearAndFocusInput: function() {
  this.setState({userInput: ''}); // Clear the input
  // We wish to focus the <input /> now!
},

render: function() {
  return (
    <div>
      <div onClick={this.clearAndFocusInput}>
        {this.state.userInput}
      </div>
      <input
        value={this.state.userInput}
        onChange={this.handleChange}
      />
    </div>
  );
}
});

And this is the weird output,

Console: console

View: (HTML Page)

HTML

Upvotes: 1

Views: 53

Answers (2)

Oliver Fencott
Oliver Fencott

Reputation: 162

By default, React components re-render when their state is changed.

Therefore, in order to get an accurate reading of the state at a given point, place your console statement inside of the render function, like so:

var SearchContainer = React.createClass({
  getInitialState: function () {
    return {
      userInput: ''
    };
  },

  handleChange: function(event) {
    var value = event.target.value;
    console.log('Value is ' + value);

    this.setState({
      userInput: value
    });
  },

  clearAndFocusInput: function() {
    this.setState({
      userInput: ''
    });
  },

  render: function() {
    var userInput = this.state.userInput;
    console.log('State is ' + userInput);

    return (
      <div>
        <div onClick={this.clearAndFocusInput}>
          {userInput}
        </div>
        <input
          value={userInput}
          onChange={this.handleChange}
        />
      </div>
    );
  }
});

Upvotes: 0

Tom
Tom

Reputation: 2611

It's because the state hasn't been updated yet. Even though you've explicitly set it using this.setState, it won't be set until the method has finished executing.

If you need the new value you could always use it from e.target.value.

Upvotes: 1

Related Questions