Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/450.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 正确处理多个连续状态更新_Javascript_Immutability_Reactjs - Fatal编程技术网

Javascript 正确处理多个连续状态更新

Javascript 正确处理多个连续状态更新,javascript,immutability,reactjs,Javascript,Immutability,Reactjs,这个例子有点做作,但请容忍我。假设我在React组件中有两个成员函数: var OrderApp = React.createClass({ getInitialState: function() { return { selectedOrders: {}, selectedLineItems: {} }; }, setOrderSelected: function(order, newSe

这个例子有点做作,但请容忍我。假设我在React组件中有两个成员函数:

var OrderApp = React.createClass({
    getInitialState: function() {
        return {
            selectedOrders: {},
            selectedLineItems: {}
        };
    },

    setOrderSelected: function(order, newSelectedState) {
        var mutation = {};
        mutation[order.id] = {$set: newSelectedState};
        var newSelectedOrders = React.addons(this.state.selectedOrders, mutation);
        _.each(order.lineItems, function(lineItem) {
            setLineItemSelected(lineItem, newSelectedState);
        });
        this.setState({selectedOrders: newSelectedOrders});
    },

    setLineItemSelected: function(lineItem, newSelectedState) {
        var mutation = {};
        mutation[lineItem.id] = {$set: newSelectedState};
        var newSelectedLineItems = React.addons(this.state.selectedLineItems, mutation);
        this.setState({seelctedLineItems: newSelectedLineItems});
    }
});
在完成调用OrderApp.setOrderSelected(order,true)时,只有最后一个lineItem selected状态在我的组件状态中发生了更改。我猜这是因为React正在批处理对setState的调用,所以当我调用时:

var newSelectedLineItems = React.addons(this.state.selectedLineItems, mutation);
在第二个函数中,我每次都会拾取原始状态,因此只有最后一个突变生效


我应该收集父函数中的所有状态突变,并且只调用setState一次吗?这对我来说有点笨拙,我想知道我是否缺少一个更简单的解决方案。

不幸的是,这是浅合并的一个问题。您必须收集更新,并一次性应用它们

我觉得有点笨重

这是一个非常好的迹象,你应该使用混音!这段代码看起来很糟糕,但是你可以在使用它的时候假装它很漂亮

var React=require('React/addons');
var UpdatesMixin={
componentDidMount:function(){
此。更新列表=[];
},
addUpdate:函数(更新){
此。更新列表。推送(更新);
if(this.\u更新\u list.length==1){
process.nextTick(函数(){
如果(!this.isMounted()){
此项。更新列表=null;
返回;
}
var state=this.\u更新\u列表.reduce(函数(状态,更新){
返回React.addons.update(state,update);
},本州);
本.设置状态(状态);
此。更新列表=[];
}.约束(这个);
}
}
};

它缓冲所有同步发生的更新,将它们应用于this.state,然后执行setState

用法如下所示(完整演示请参见requirebin)

this.addUpdate({a:{b:{$set:'foo'});
this.addUpdate({a:{c:{$set:'bar'});

有些地方可以对其进行优化(例如,通过合并更新对象),但您可以稍后在不更改组件的情况下进行优化。

在组件内的给定执行线程中,您不应该多次调用
this.setState

因此,您有两个选择:

使用forceUpdate而不是setState

您不必使用
this.setState
-您可以直接修改状态,并在完成后使用
this.forceUpdate

这里要记住的主要一点是,一旦您开始直接修改它,您就应该将
this.state
视为已受污染。即:在调用
this.forceUpdate
之前,不要使用您知道已修改的状态或属性。这通常不是问题

在处理
this.state
中的嵌套对象时,我绝对喜欢这种方法。就我个人而言,我不太喜欢
React.addons.update
,因为我觉得语法非常笨拙。我更喜欢直接修改和
forceUpdate

创建一个对象,直到最后在setState中使用它时为止


收集所有更改的对象,在执行线程结束时传递到
this.setState

作为全新的反应对象,我没有考虑在这里使用Mixin,但这肯定会让人感觉更干净。我的一个问题涉及在解决方案中调用process.nextTick。我能找到的唯一文档表明这是一个特定于节点的库。在客户端上处理更新时,是否有类似的库可用于缓冲更新?如果您不使用browserify/webpack,可以下载一个独立的垫片:-大多数人使用cjs模块,您必须自己编译一些库,因为npm通常是唯一的分发介质。我真的我接受了你对我问题的回答。我之所以将Mike的答案标记为接受,只是因为它不需要外部依赖。我认为有一个强有力的理由可以证明,你的答案是从一种更具反应性的心态来解决问题的。谢谢你的帮助。这打乱了所有的应用程序逻辑,在使用forceUpdate时什么都没有显示