我正在尝试实现一个队列,其中用户可以将项目从一个列表切换到另一个列表。即从“可用”到“有客户端”,其中队列的状态保存在根 React 组件中,如下所示:
this.state = {
queue: {
available: [{ name: "example", id: 1 }, ...],
withClient: [],
unavailable: []
}
};
但是我的移动功能坏了:
move(id, from, to) {
let newQueue = deepCopy(this.state.queue);
console.log("NEW QUEUE FROM MOVE", newQueue); // { [from]: [], [to]: [undefined] }
console.log("QUEUE IN STATE FROM MOVE", this.state.queue); // { [from]: [{...}], [to]: [] }
let temp = newQueue[from].find(x => x.id === id);
newQueue[from] = this.state.queue[from].filter(x =>
x.id !== id
);
newQueue[to] = this.state.queue[to].concat(temp);
this.setState({
queue: newQueue
});
}
我希望 2 个 console.logs 相同。这里似乎发生了某种我不理解的竞争条件。它导致出现错误 Cannot read property 'id' of undefined
现在唯一的方法是从包含在“可用”列表中的每个项目中的 HelpedButton
组件触发移动,该组件获得传递的 Prop :
class HelpedButton extends React.Component {
constructor() {
super();
this.clickWrapper = this.clickWrapper.bind(this);
}
clickWrapper() {
console.log("I have id right?", this.props.id); //outputs as expected
this.props.move(this.props.id, "available", "withClient");
}
render() {
return (
<span style={this.props.style}>
<button onClick={this.clickWrapper}>
<strong>Helped A Customer</strong>
</button>
</span>
);
}
}
export default HelpedButton;
我不认为 deepCopy
函数有什么问题,但这里是从 node_modules 导入的文件:
"use strict";
function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
module.exports = deepCopy;
最佳答案
react documentation推荐的方式使 setState 依赖于先前的状态是使用看起来像这样的更新程序形式 setState((prevState,prevProp)=>{})
。使用此方法,您的 move
函数将如下所示。
move(id, from, to) {
let temp = newQueue[from].find(x => x === x.id);
newQueue[from] = this.state.queue[from].filter(x =>
x.id !== id
);
newQueue[to] = this.state.queue[to].concat(temp);
this.setState((prevState)=>{
queue: {
...prevState.queue,
[from]: prevState.queue[from](o => x.id !== id),
[to]: [from]: prevState.queue[from].concat(prevState.queue[from].find(x => x === x.id))
}
});
}
我相信您看到不同输出的原因是 console.log
输出一个事件对象,这意味着如果您运行 console.log(obj)
并稍后更改 obj 参数显示的参数是更改。尝试使用 console.log("obj: "+ JSON.strignify(obj))
进行调试。
这里详细说明了为什么在依赖 react docs 中的先前状态时应该调用 setState
的异步方法
关于javascript - react 切换列表竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49743845/