【发布时间】:2015-09-13 15:21:04
【问题描述】:
说真的,这就像 Javascript 的双缝实验。
基本上我所拥有的是一系列步骤。我想要发生的是,当用户向列表中添加新步骤时,activeStepId 的状态被设置为新添加的步骤(它在步骤列表中突出显示)。
正如您将在下面看到的,我正在监听商店中的更改并触发组件中的 onChange 事件。
现在,疯狂的部分来了:
每当我进行比较newState.steps.length > this.state.steps.length 以查看新状态是否比前一个状态有更多步骤时,不知何故旧状态已经更新到新状态,尽管 setState 甚至还没有被调用!
现在,我知道您可能认为我的代码中还有其他地方我正在更新状态而没有意识到。是的,我也是这么想的,但是当我删除下面对 setState 的调用然后检查结果时,它起作用了! this.state.steps.length 本来应该是这样:旧值,而不是新值。
在这一点上我已经花了好几个小时,但我真的不知道发生了什么。
componentDidMount: function(){
FlowStepStore.on('change', this.onChange);
},
onChange: function(){
var newState = this.getState();
// If we've just added a step, set it as active
if(newState.steps.length > this.state.steps.length){
newState.activeStepId = newState.steps[newState.steps.length - 1].id;
}
this.setState(newState);
},
getState: function(){
return {
activeStepId: this.activeStepId(),
steps: FlowStepStore.getSteps()
};
},
我也尝试过使用不同的方法,通过使用 componentDidUpdate(prevProps, prevState) 执行步数比较并将 prevState 与 this.state 进行比较,但我遇到了完全相同的问题!不知何故,prevState 已经等于当前状态。
大吃一惊。
救命!
【问题讨论】:
-
你做了什么来调试这个?你在使用断点吗?似乎在您比较长度之前分配已经发生,因此有问题的代码将早于此处的代码。断点和调试说明在stackoverflow.com/tags/debugging/info
-
由于 this.state.steps 包含对 FlowStepStore 中数组的引用,因此您必须确保不要更改此引用,而是创建一个新数组。是这样吗?
-
@Mousey 我已经调试了我能想到的所有方法。如果您执行
console.log(this.state.steps.length); console.log(newState.steps.length);并将其放在 onChange 函数的最顶部,则两者的值相同,这意味着在该函数的最开始时状态已经以某种方式更新。但是,如果您在onChange函数的末尾删除对this.setState的调用,那么this.state.steps.length应该比newState.steps.length小1。更疯狂的是,如果您进行调试;setState之前的语句,值在到达之前就更新了 -
@Heap 你是个天才。我没有意识到我的状态直接引用了 store 中的一个变量,该变量在设置组件状态之前已经更新。将其修改为返回 _steps.slice() 而不仅仅是 _steps,现在它可以工作了!感谢您为我节省了数小时的时间!
标签: javascript asynchronous reactjs