11

In this ReactJS code in component I would expect this.setState( {b_MyPartyCat: value} ) to update this.state.b_MyPartyCat so the two console.log statements in updatePartyCategory() show the same value, but they don't.

var MyIconButton = React.createClass({

  handleSubmit: function(e) {
    e.preventDefault();

    var b_buttonOn = false;
    if (this.props.pressed === true) {
      b_buttonOn = false;
    }
    else {
      b_buttonOn = true;
    }
    this.props.updateFilter( b_buttonOn ); 
  },

  render: function() {   
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input type="image" src={this.props.pressed ? this.props.onpic : this.props.offpic }></input>
        </form>
      </div>
    );
  }
});


var MyPartyCatButton = React.createClass({

  render: function() {
    return (
      <MyIconButton pressed={this.props.pressed} updateFilter={this.props.updateFilter} onpic="static/images/icon1.jpeg" offpic="static/images/off-icon.jpg"/>
    );
  }
});

//
// Main App view
var MyHomeView = React.createClass({
  getInitialState: function() {
    // This is where I'll eventually get data from the server.
    return {
      b_MyPartyCat: true
    };
  },

  updatePartyCategory: function(value) {
    // Eventually will write value to the server.
    this.setState( {b_MyPartyCat: value} );

    console.log("INSIDE: MyHomeView() updatePartyCategory() value = " + value );
    console.log("INSIDE: MyHomeView() updatePartyCategory() this.state.b_MyPartyCat = " + this.state.b_MyPartyCat );

  },

  render: function() {
    return (
        <div>
         <MyPartyCatButton pressed={this.state.b_MyPartyCat} updateFilter={this.updatePartyCategory}/>
        </div>

        // Eventually will have 3 other categories i.e. Books, Skateboards, Trees !
    );
  }
});
Giant Elk
  • 5,375
  • 9
  • 43
  • 56

1 Answers1

42

setState actually queues a state update. If you want to do something after it's actually executed, you can pass a callback as the second argument.

updatePartyCategory: function(value) {
    this.setState({b_MyPartyCat: value}, function(){
        console.log(this.state.value === value); // true
    }.bind(this));
},
Brigand
  • 84,529
  • 20
  • 165
  • 173
  • 1
    Got it thanks, that's what I suspected, but didn't think about callbacks, I'm still wearing my C++ hat. I'll use `value` to keep it simple without needing the callback, but this is good to know, just in case !-) http://facebook.github.io/react/docs/component-api.html – Giant Elk Aug 07 '14 at 02:38
  • 1
    Is this absolutely required too `.bind(this)`, what happens without the .bind? I can't tell the difference when I try with or without .bind. – Giant Elk Aug 07 '14 at 02:41
  • @GiantElk: In [typical JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) you do, with [React's Autobinding](http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation) you don't! :-) – go-oleg Aug 07 '14 at 03:14
  • Well if removing .bind still has it working, then it must be calling it in that context. I tracing through the source after watching the component and state change object passed through 7 functions and 3 files :-) – Brigand Aug 07 '14 at 05:30
  • 2
    Yes, the callback is intentionally called with the component as context. – Sophie Alpert Aug 07 '14 at 20:48
  • With ES6 you do not need `.bind(this)` instead use `this.setState({b_MyPartyCat: value}, ()=>{ console.log(this.state.value === value); // true });` – dane Jul 18 '16 at 14:35