【问题标题】:React + Reflux - Issue with queue and timeout for components sharing the same storeReact + Reflux - 共享同一存储的组件的队列和超时问题
【发布时间】:2015-10-21 13:47:00
【问题描述】:

我有一个这样的组件,

我已经为示例重构了它,不使用 valueLink 来帮助说明问题。

在这个例子中,我有一个 Field 组件,多次渲染 (3) 都绑定到商店中的同一个属性。这个概念很简单,当一个输入发生变化时,它会反映到其他的。

如果您键入得非常快(敲几个键)并且事件排队然后以循环结束,其中每个组件都根据来自另一个组件的较早状态更新而更新,那么问题就来了。如果你打字慢,我想队列上的滴答超时更慢,它工作正常。

使用值链接可以观察到类似的症状。但它几乎在做同样的事情,所以我希望如此。

var App = React.createClass({

  render: function() {
    return  <Field dataItemName="PropertyA" />
        <Field dataItemName="PropertyA" />
        <Field dataItemName="PropertyA" />;
  }
});

var RecordStore = Reflux.createStore({
    mixins: [StateMixin],
    listenables: [FormActions, RecordActions],

    init: function () {        
    },

    getInitialState: function () {        
        return { PropertyA : 'test' };
    },

    valueChanged: function (newVal, propName) {        
        var o = {};
        if (newVal !== this.state[propName].value) {
            o[propName] = newVal;           
            this.setState(o);
        }
    }
});

var Field = React.createClass({
    mixins: [Reflux.ListenerMixin],
    getInitialState: function () {
        return ({           
            value: RecordStore.state[this.props.dataItemName].value          
        })
    },
    componentDidMount: function(){
        this.listenTo(RecordStore[this.props.dataItemName], this.updateValue);              
    },
    updateValue: function (value) {       
        this.setState({ value: value.value });
    },
    shouldComponentUpdate: function (nextProps, nextState) {     
        return  nextState.value != this.state.value;
    },
    componentDidUpdate: function (prevProps, prevState) {       
        RecordActions.valueChanged(this.state.value, this.props.dataItemName);
    },
    handleInput: function (event) {
        this.setState({ value: event.target.value });
    },
    render: function () {                  
       return (
         <div className='form-group'>
           <label htmlFor={this._reactInternalInstance._rootNodeID+'_input'}>{this.props.label}</label>
           <input className="form-control" value={this.state.value} id={this._reactInternalInstance._rootNodeID+'_input'} onChange={this.handleInput} />          
         </div>
        );
    }
});

我考虑过在更新存储中的值之前使用自己的超时,即等到用户完成输入;但我想知道框架/lib 中是否有任何东西可以处理它?

谢谢

【问题讨论】:

    标签: reactjs refluxjs


    【解决方案1】:

    好的,对于任何使用超时寻找解决方案的人来说,这是一个答案。

    问题可以追溯到 React 的 drainQueue 调用队列中剩余的项目。在这个解决方案中,我只是想推迟将 updateValue 放入队列,直到我们确定通过敲击键盘创建的事件的速度已经完成。

    通过将componentDidUpdate 更改为使用超时(我认为它只需要> 0)意味着每次击键都不会触发事件,从而否定了我最初询问的问题。

    componentDidUpdate: function (prevProps, prevState) { 
         **var _self = this;
         clearTimeout(_self.state.inputtimer);        
        _self.state.inputtimer = setTimeout(function () { RecordActions.valueChanged(_self.state.value, _self.props.dataItemName);},50);**
    }
    

    这似乎已经完成了这项工作。非常欢迎任何 cmets 或其他解决方案。我宁愿使用 valueLink 来完成它(我想我仍然可以这么想)并且可以为我猜的超时创建一个 mixin。

    这是drainQueue func 供参考。

    function drainQueue() {
        if (draining) {
            return;
        }
        var timeout = setTimeout(cleanUpNextTick);
        draining = true;
    
        var len = queue.length;
        while(len) {
            currentQueue = queue;
            queue = [];
            while (++queueIndex < len) {
                currentQueue[queueIndex].run();
            }
            queueIndex = -1;
            len = queue.length;
        }
        currentQueue = null;
        draining = false;
        clearTimeout(timeout);
    }
    

    谢谢

    【讨论】:

      猜你喜欢
      • 2015-04-13
      • 1970-01-01
      • 2015-05-21
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      相关资源
      最近更新 更多