代码之家  ›  专栏  ›  技术社区  ›  Terence Chow

反应/通量,设置多个状态

  •  1
  • Terence Chow  · 技术社区  · 10 年前

    我是新来的反应者,我正在为我的数据模型使用状态。

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

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

    我使用的是标准通量模式。

    以下是相关代码:

    菜单.js

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

    菜单存储.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
      }
    
    });
    

    导航.js

    toggleMenu:function(){
        Actions.toggleMenu(); //in my actions.js it dispatches TOGGLE_MENU
    }
    
    render:function(){
         return <div onClick={this.toggleMenu}>My Nav button</div>
    }
    

    我想我发现的是,我正在设置用户的个人资料图片的状态,但没有更改。这是正确的做事方式吗?或者我应该发出单独的更改事件,从而使用单独的回调,以便单独设置状态?

    一个相关的问题是React是否会在意我是否设置了未更改的状态。一、 e区分算法是否忽略了用户的个人资料图片,因为它没有改变,因此对React没有影响?或者,我将状态设置为react这一事实是否隐含地告诉react“发生了变化”?

    哪种是正确的反应/通量模式?在一个回调中设置所有状态?还是分别设置所有状态?

    1 回复  |  直到 10 年前
        1
  •  6
  •   gcedo    10 年前

    我希望,在与React和Flux合作时学到的一些东西可以改进您的方法:

    将整个状态与发出的事件一起发送

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

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

    我建议您改用另一种模式,在这种模式下,商店每次发出事件时都会发送整个状态,无论事件是什么:

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

    然后在组件中:

    _onChange:function(snapshot){
        this.setState({
            opened: snapshot.opened,
            profilePicUrl: snapshot.profilePicUrl
        })
    }
    

    这样你的商店 按比例放大 ,无论您想在存储中保留多少数据。

    考虑使用Immutable。js或附带的不变性助手

    一个相关的问题是React是否会在意我是否设置了未更改的状态。

    React将在虚拟DOM中触发虚拟重新渲染。然后,它将执行diff算法。由于没有任何更改,因此不会重新渲染任何内容。 您可以通过重写 shouldComponentUpdate :

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

    我强烈建议您开始使用 immutability helpers Immutable.js 通过这种方式,管理整个重新渲染过程变得更容易,因为了解什么时候发生了真正的变化变得很简单。

    此外,请记住React速度极快。除非你有>100个组件侦听更改,有时最好是浪费一些重新渲染周期,而不是编写一个复杂的 should组件更新 .

    代码可读性与性能

    我想我觉得奇怪的是,我正在设置用户的个人资料图片的状态,但它没有改变。

    这真的是一种权衡。如果你有100个组件在监听同一个商店,其中一些组件只对一个事件感兴趣,另一些组件对另一个事件有兴趣,那么就会有不同的事件(无论如何,你都会继续发送整个快照)。否则,我建议保持代码简单:只发布一个事件。

    助焊剂有不同的口味

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