2016-02-20 37 views
0

我有2个组件。一个项目容器和一个项目设置面板(稍后会有更多的项目设置面板)。在调用Flux Store操作时,setState未更新状态

我在面板中调用“switchSubmit”函数来更新状态,然后调用“handleSubmit”函数,该函数包含基于开关按钮的值更新Flux Store的操作,我正在设置状态但它总是似乎是我的动作被调用时选择的以前的值。

我读过setState是不同步的,我已经看到了一些例子,但不知道如何应用正确的调用和函数来设置状态,并有更新的状态准备好在调用此操作时使用我写的特定代码。

这里是我的代码:

var React = require('react/addons'); 
var Actions = require('../../Actions'); 
var ConfigurationStore = require('../../stores/Configuration'); 

var Controller = React.createClass({ 
    getInitialState: function() { 

     ConfigurationStore.reset(); 

     Actions.getConfigurationSettings(); 

     return this.getStateFromStores(); 
    }, 

    getStateFromStores: function() { 
     return { 
      configuration: ConfigurationStore.getState() 
     }; 
    }, 

    componentDidMount: function() { 
     ConfigurationStore.addChangeListener(this.onStoreChange); 
    }, 

    componentWillUnmount: function() { 
     ConfigurationStore.removeChangeListener(this.onStoreChange); 
    }, 

    onStoreChange: function() { 
     this.setState(this.getStateFromStores()); 
    }, 


    render: function() { 

     return (
      <section className="section-settings container"> 
       <h1 className="page-header">Projects</h1> 
       <div className="row"> 
        <div className="col-sm-12"> 
         <div className="row"> 
          <div className="col-sm-3"> 
          </div> 
          <div className="col-sm-9"> 
           <h2>Project Settings</h2> 
           <hr /> 
           <ProjectContainer data={this.state.configuration} /> 
          </div> 
         </div> 
        </div> 
       </div> 
      </section> 
     ); 

    } 

});  


var ProjectContainer = React.createClass({ 

    getInitialState: function() { 
     return { 
      active: false 

     }; 
    }, 

    componentWillReceiveProps: function (nextProps) { 
     this.setState({ 
      active: nextProps.data.active 
     }); 
    }, 

    render: function() { 
     return (
      <div> 
       <ProjectPanel data={this.props.data}></ProjectPanel> 
      </div> 
     ); 

    } 
}); 


var ProjectPanel = React.createClass({ 

    getInitialState: function() { 
     return { 
      active: false 
     }; 
    }, 

    componentWillReceiveProps: function (nextProps) { 
     this.setState({ 
      active: nextProps.data.active 
     }); 
    }, 

    handleSubmit: function() { 
     Actions.updateConfigurationSettings({ 
      active: this.state.active 
     }); 
    }, 

    switchSubmit: function(event) { 
     event.stopPropagation(); 

     this.setState({ 
      active: event.currentTarget.checked 
     }); 

     this.handleSubmit(); 

    }, 

    render: function() { 

     var formElements = (
       <fieldset> 
        <SwitchButton 
         name="switch-1" 
         onChange={this.switchSubmit} 
         checked={this.props.active} 
        /> 
       </fieldset> 
      ); 
     } 

     return (
      <div className="project-holder"> 
       <div className="project-config"> 
        <form onSubmit={this.handleSubmit}> 
         {formElements} 
        </form> 
       </div> 
      </div> 
     ); 
    } 
}); 

任何帮助将不胜感激!

回答

1

要直接回答您的问题,setState接受回调,可用于推迟代码,直到渲染完成后。但是,你不应该在你的场景中使用它。

我在代码中看到的问题是,您有'活动'状态的多个真相来源。

我已经更新了你的代码来解决这个问题:

var React = require('react/addons'); 
var Actions = require('../../Actions'); 
var ConfigurationStore = require('../../stores/Configuration'); 

var Controller = React.createClass({ 
    getInitialState: function() { 

     ConfigurationStore.reset(); 

     Actions.getConfigurationSettings(); 

     return this.getStateFromStores(); 
    }, 

    getStateFromStores: function() { 
     return { 
      configuration: ConfigurationStore.getState() 
     }; 
    }, 

    componentDidMount: function() { 
     ConfigurationStore.addChangeListener(this.onStoreChange); 
    }, 

    componentWillUnmount: function() { 
     ConfigurationStore.removeChangeListener(this.onStoreChange); 
    }, 

    onStoreChange: function() { 
     this.setState(this.getStateFromStores()); 
    }, 


    render: function() { 

     return (
      <section className="section-settings container"> 
       <h1 className="page-header">Projects</h1> 
       <div className="row"> 
        <div className="col-sm-12"> 
         <div className="row"> 
          <div className="col-sm-3"> 
          </div> 
          <div className="col-sm-9"> 
           <h2>Project Settings</h2> 
           <hr /> 
           <ProjectContainer data={this.state.configuration} /> 
          </div> 
         </div> 
        </div> 
       </div> 
      </section> 
     ); 

    } 

});  

var ProjectContainer = React.createClass({ 
    render: function() { 
     return (
      <div> 
       <ProjectPanel data={this.props.data}></ProjectPanel> 
      </div> 
     ); 

    } 
}); 


var ProjectPanel = React.createClass({ 
    handleSubmit: function() { 
     // Do something interesting on submit. 
    }, 

    switchSubmit: function(event) { 
     event.stopPropagation(); 
     Actions.updateConfigurationSettings({ 
      active: event.target.checked 
     }); 
    }, 

    render: function() { 

     var formElements = (
       <fieldset> 
        <SwitchButton 
         name="switch-1" 
         onChange={this.switchSubmit} 
         checked={this.props.data.active} 
        /> 
       </fieldset> 
      ); 
     } 

     return (
      <div className="project-holder"> 
       <div className="project-config"> 
        <form onSubmit={this.handleSubmit}> 
         {formElements} 
        </form> 
       </div> 
      </div> 
     ); 
    } 
}); 

没有必要无论是在ProjectContainerProjectPanel持有本地状态。 “活动”状态通过道具流向这些组件。

我没有在您的handleSubmit按钮中放置任何代码,因为我不觉得您最初有什么意义。你只需要你想要提交的任何代码就可以运行。

+0

感谢那些非常有意义。唯一我不明白的是当你触发Action时,你用于switchSubmit的值.updateConfigurationSettings不应该使用switch事件值而是使用!this.props.data.active设置活动值。 – BennyTicklez

+0

是的,你是对的。我使用的事实是它只是一个布尔值,所以我们知道它将与改变之前的this.props.active相反。但是,从元素本身获取它更为正确。我已经更新了我的答案。 – LodeRunner28

+0

令人惊叹的东西。我投了这个票!你的解释很容易理解,代码完美工作 – BennyTicklez

1

this.setState允许回调函数,如果您需要在状态完全更改后执行某些操作。

语法应该是这样的:

switchSubmit: function(event) { 
    event.stopPropagation(); 

    this.setState({ 
     active: event.currentTarget.checked 
    }, this.handleSubmit); 



}, 
相关问题