【问题标题】:React JSX Dynamically changing the state of a component. Best practice and whyReact JSX 动态改变组件的状态。最佳实践和原因
【发布时间】:2021-01-23 17:24:35
【问题描述】:

我是 React 的新手,我正在关注 youtube 上的一个视频,并正在努力 + 在上面添加更多内容。

我有一个按钮,当点击它时,它会减少对象的value。在视频中,老师将状态复制到一个新数组中,找到项目的索引,进行所需的操作,然后使用this.setState()再次设置状态

这是我用来练习的硬编码状态。我希望当单击按钮时,value 减少 1,除非该值小于或等于 0

  state = {
    counters: [
      { id: 1, name: "Drink 1", value: 4 },
      { id: 2, name: "Drink 2", value: 0 },
      { id: 3, name: "Drink 3", value: 0 },
      { id: 4, name: "Drink 4", value: 0 },
    ],
  };

//and what I'm passing down to other components:

{this.state.counters.map((counter) => (
          <Counter
            key={counter.id}
            counter={counter}
            onDeletion={this.handleDeletion}
            onIncrement={this.handleIncrement}
            onDecrement={this.handleDecrement}
          ></Counter>
))}

视频代码:

handleDecrement = (counter) => {
    const counters = [...this.state.counters];
    const indexOfCounters = counters.indexOf(counter);
    counters[indexOfCounters] = { ...counter };
    counters[indexOfCounters].value <= 0
      ? (counters[indexOfCounters].value = 0)
      : counters[indexOfCounters].value--;
    this.setState({ counters });
  };

这是我想出的代码,它赋予按钮相同的功能:

handleDecrement = (counter) => {
    counter.value <= 0 ? (counter.value = 0) : counter.value--;
    this.setState(counter);
  };

两种方式都提供了所需的功能,我只是犹豫要不要走,以防这违反最佳实践。

通过阅读文档和类似的状态相关问题,我可以猜测视频中提供的方式改变了完整的状态,而我的方式只改变了其中的一个对象。 youtube 代码是否是解决此问题的正确方法,因为正在设置整个状态并且我们保持单一的事实来源?我的做法是不好的做法吗?

视频来自 Mosh 编程:https://www.youtube.com/watch?v=Ke90Tje7VS0

【问题讨论】:

  • 在第二个示例中,您将使用更新的整数值counter 覆盖先前存储在状态中的对象。
  • 抛开实践不谈,你的更新方式不是意味着你有不同的状态结构吗?
  • @RameshReddy 是的,那是正确的,我已经更新了我的代码以显示我在 Counter 组件中传递的内容。这就是我得到命名的地方。
  • @pilchard 正确。并且视频 sn-p 会覆盖整个状态,而不仅仅是一个对象。这就是我在理解解决此问题的最佳方法方面遇到的问题。
  • 哦,我明白了,您正在传递对计数器对象的引用。这样做的问题是您通过直接更改引用的对象来改变状态。视频中的代码虽然冗长,但通过在状态对象的每个级别上克隆(通过扩展运算符)来避免改变状态。

标签: javascript reactjs jsx


【解决方案1】:

我认为您只是对更新 counters 数组而不是其中的对象 (counter) 背后的原因感到困惑。

这是因为state 应该始终以不可变的方式更新。在您的情况下,由于 value 在一个对象中,而该对象又在一个数组中,counters 数组和 counter 对象在更新后应该有一个新的引用,以正确通知 React state 已更改.

在您的 sn-p 中,this.setState(counter); 将用counter 覆盖状态(因此其他counters 被删除)并且您也在改变对象。

如果你想让代码简洁一点,同时确保状态更新不变,这里有一个替代方案:

handleDecrement = (counter) => {
  this.setState(prevState => ({counters: prevState.counters.map(c => {
      return (c.id === counter.id && c.value > 0) ? {...c, value: c.value - 1} : c;
  })}));
};

在上面的 sn -p map 创建一个新数组,{} 对象字面量语法创建一个新的 counter 对象。

【讨论】:

    猜你喜欢
    • 2016-06-05
    • 2022-07-18
    • 2018-03-21
    • 2020-11-14
    • 1970-01-01
    • 2018-10-03
    • 2023-03-14
    • 1970-01-01
    • 2014-02-20
    相关资源
    最近更新 更多