首页 文章

反应切换列出竞争条件?

提问于
浏览
1

我正在尝试实现一个队列,其中用户可以将项目从一个列表切换到另一个列表 . 即从“可用”到“与客户端”,其中队列的状态保存在根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

现在,从"Available"列表中的每个项目中包含的 HelpedButton 组件触发移动的唯一方式是传递道具:

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;

我't think there'函数没有't think there',但是这里是来自node_modules的导入文件:

"use strict";

function deepCopy(obj) {
  return JSON.parse(JSON.stringify(obj));
}

module.exports = deepCopy;

1 回答

  • 1

    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 的异步方法的原因

相关问题