2

我有一个像这样的组件,

我已经为示例重构了它,不使用 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中是否有任何东西可以处理它?

谢谢

4

1 回答 1

0

好的,所以这里是任何寻找使用超时解决方案的人的答案。

问题可以追溯到 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);**
}

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

这是 drainQueue 函数供参考。

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-07-30T09:36:06.207 回答