React/Flux,设置多个状态

Ter*_*how 1 reactjs reactjs-flux

我是新手做出反应,我正在为我的数据模型使用状态.

我有一个菜单,通过状态显示用户的个人资料图片.这是状态,因为用户可以更改他的个人资料图片.

我希望菜单从左侧滑入,最初隐藏.因此,我想将菜单的打开/关闭状态添加为状态.

我正在使用标准的Flux模式.

这是相关代码:

Menu.js

_onChange:function(){
    this.setState({
        opened: MenuStore.getMenuState(),
        profilePicUrl: MenuStore.getUserPic()
    })
},

componentDidMount:function(){
    MenuStore.addChangeListener(this._onChange)
}
Run Code Online (Sandbox Code Playgroud)

MenuStore.js

MenuStore = assign({},EventEmitter.prototype,{
    emitChange: function() {
        this.emit(CHANGE_EVENT);
    },

    addChangeListener: function(callback) {
        this.on(CHANGE_EVENT, callback);
    },

    ...(rest of class not shown)
})

MenuStore.dispatchToken = Dispatcher.register(function(action) {

  switch(action.type) {

    case ActionTypes.RECEIVE_USER_DATA:
       _userData = action.details;
        MenuStore.emitChange();         
        break;

    case ActionTypes.TOGGLE_MENU:
        _opened = !_opened;
        MenuStore.emitChange();
        break;

    default:
      // do nothing
  }

});
Run Code Online (Sandbox Code Playgroud)

Nav.js

toggleMenu:function(){
    Actions.toggleMenu(); //in my actions.js it dispatches TOGGLE_MENU
}

render:function(){
     return <div onClick={this.toggleMenu}>My Nav button</div>
}
Run Code Online (Sandbox Code Playgroud)

我想我觉得奇怪的是,我正在设置用户的个人资料图片的状态而不更改.这是正确的做事方式吗?或者我应该发出单独的更改事件,因此使用单独的回调,以便我分别设置状态?

一个相关的问题是,如果我设置了没有改变的东西的状态,React是否会关心.即,差异算法忽略用户的个人资料图片,因为它没有改变,因此对React没有影响?或者我确实将状态设置为反应,隐含地告诉React"某些事情发生了变化"?

哪个是正确的React/Flux模式?在一个回调中设置所有状态?或分别设置所有状态?

gce*_*edo 6

我学习了一些与React和Flux一起工作的东西,希望能改进你的方法:

使用发出的事件发送整个状态

在您的示例中,您正在发出一个事件,然后该组件正在请求数据:

_onChange:function(){
    this.setState({
        opened: MenuStore.getMenuState(),
        profilePicUrl: MenuStore.getUserPic()
    })
}
Run Code Online (Sandbox Code Playgroud)

我建议你转移到另一种模式,商店每次发出一个事件时都会发送整个状态,无论事件如何:

case ActionTypes.TOGGLE_MENU:
    _opened = !_opened;
    MenuStore.emitChange({opened: _opened, /* [...] */});
    break;
Run Code Online (Sandbox Code Playgroud)

然后在你的组件中:

_onChange:function(snapshot){
    this.setState({
        opened: snapshot.opened,
        profilePicUrl: snapshot.profilePicUrl
    })
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,无论您希望在商店中保留多少数据,您的商店都可以扩展.

考虑使用Immutable.js或运送不变性助手

一个相关的问题是,如果我设置了没有改变的东西的状态,React是否会关心.

React将在虚拟DOM中触发虚拟重新渲染.然后,它将执行diff算法.没有任何改变,任何东西都不会被重新渲染.您可以通过覆盖来避免这种情况shouldComponentUpdate:

在收到新道具或州时,在渲染之前调用.初始渲染或使用forceUpdate时不调用此方法.当您确定转换到新的道具和状态不需要更新组件时,请将此作为返回false的机会.

我强烈建议你开始使用immutability helpersImmutable.js.通过这种方式,管理整个重新渲染过程变得更加容易,因为当事情真正发生变化时,理解变得微不足道.

另外,请记住React非常快.除非你有> 100个组件监听更改,否则有时候浪费一些浪费的重新渲染周期会更好,而不是写一个复杂的shouldComponentUpdate.

代码可读性与性能

我想我觉得奇怪的是,我正在设置用户的个人资料图片的状态而不更改.

这真的是一种折衷.如果你有大约100个组件正在监听同一个商店,其中一些只对一个事件感兴趣,而另一个对另一个事件感兴趣,那么就会出现不同的事件(你会继续发送整个快照).否则,我建议保持你的代码简单:只发布一个事件.

助焊剂有不同的味道

现在有一些库实现了从Flux中获取的想法.我建议你看看Reflux,尤其是Redux.