Search code examples
javascriptreactjsfluxrefluxjs

React - why I still got same result when I already change the state


Below is my content.jsx

var React = require('react');
var Reflux = require('reflux');

var ApplyInfo = require('./applyInfo');

var Actions = require('../actions/actions');
var DataStore = require('../stores/data-store');


module.exports = React.createClass({
  mixins: [
    Reflux.listenTo(DataStore, 'onChange'),
  ],
  onChange: function(event, allDatas) {
    console.log("o");
    this.setState({
      applyDatas: allDatas
    })
  },
  getInitialState: function() {
    console.log('g');
    return {
      section: "go_3",
      applyDatas: {test : "AAA"}
    }
  },
  componentWillMount: function() {
    console.log('c');
    Actions.getDatas();
  },
  render: function() {
    console.log("content = " + this.state.applyDatas.test);
    return <div>
      <div className="content">
        <ApplyInfo showValue={this.state.applyDatas.test} print={console.log("showValue = " + this.state.applyDatas.test)} />

       .......

Below is my applyInfo.jsx

var React = require('react');
var Reflux = require('reflux');
var TextInput = require('./TextInput');
var Option = require('./option');
var Actions = require('../actions/actions');


module.exports = React.createClass({
  getInitialState: function() {
    return {
      // .....
      applyInfoDatas: this.props.showValue
    }
  },
  render: function() {
    console.log("value = " + this.state.applyInfoDatas);
    return <div className="section_3">

      <div className="info_input">
        <div className="demo_a demo2 lll">
          <TextInput id="loanAmount" title="loan" showValue={this.state.applyInfoDatas}/>
        </div>
      </div>

Below is my data-store.jsx

var Refulx = require('reflux');
var Actions = require('../actions/actions');

var allDatas = {test : "AAB"};
module.exports = Refulx.createStore({
  listenables: Actions,

  getDatas: function() {
    console.log("ready to send allDatas");
    this.trigger('change', allDatas);
  }
});

and here is my console.log result from chrome

g
c
content = AAA
showValue = AAA
value = AAA
ready to send allDatas
o
content = AAB
showValue = AAB
value = AAA

Why I still got "value = AAA" in the end , i thought it should be "AAB" which I already change it when call Actions.getDatas and setState.


Solution

  • Looks like you need to change your ApplyInfo component. The flow in your test is as follows:

    • Content.jsx has state of 'AAA', and passed it down as prop to ApplyInfo.jsx
    • ApplyInfo component sets its own initial state to 'AAA'
    • ApplyInfo renders state = 'AAA'
    • store changes to 'AAB' and emits change
    • Content.jsx updates state to 'AAB', and passes state down as prop to ApplyInfo
    • The state inside ApplyInfo is not updated; getInitialState is only called once. The second time the component is already rendered, and will only be updated, so getInitialState is not called.
    • so ApplyInfo still has state 'AAA', which it renders.

    Two ways to deal with this:

    1. You could simply render showValues as a prop. (but then you will need an onChange function in your TextInput component)
    2. Add a componentWillReceiveProps to update your state (see answer by @zvona)

    Ad 1. To make ApplyInfos.jsx simply render new showValue:

    module.exports = React.createClass({
      render: function() {
        console.log("value = " + this.props.showValue);
        return <div className="section_3">
    
          <div className="info_input">
            <div className="demo_a demo2 lll">
              <TextInput id="loanAmount" title="loan" showValue={this.props.showValue}/>
            </div>
          </div>