Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.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 React JSX动态更改组件的状态。最佳做法及其原因_Javascript_Reactjs_Jsx - Fatal编程技术网

Javascript React JSX动态更改组件的状态。最佳做法及其原因

Javascript React JSX动态更改组件的状态。最佳做法及其原因,javascript,reactjs,jsx,Javascript,Reactjs,Jsx,我是React的新手,正在关注youtube上的一段视频,并在上面添加了更多内容 我有一个按钮,当点击时,它会降低对象的值。在视频中,教师将状态复制到一个新数组中,找到项目的索引,执行所需的操作,然后使用this.setState() 这是我用来练习的硬编码状态。我希望当单击按钮时,值减少1,除非该值小于或等于0 state = { counters: [ { id: 1, name: "Drink 1", value: 4 }, { id

我是React的新手,正在关注youtube上的一段视频,并在上面添加了更多内容

我有一个按钮,当点击时,它会降低对象的
值。在视频中,教师将状态复制到一个新数组中,找到项目的索引,执行所需的操作,然后使用
this.setState()

这是我用来练习的硬编码状态。我希望当单击按钮时,
减少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>
))}
状态={
计数器:[
{id:1,名称:“饮料1”,值:4},
{id:2,名称:“饮料2”,值:0},
{id:3,名称:“饮料3”,值:0},
{id:4,名称:“饮料4”,值:0},
],
};
//以及我要传递给其他组件的内容:
{this.state.counters.map((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=(计数器)=>{
常量计数器=[…this.state.counters];
常量indexOfCounters=计数器。indexOf(计数器);
计数器[索引计数器]={…计数器};
计数器[indexOfCounters]。值{

counter.value我想您只是对更新
计数器
数组而不是其中的对象(
计数器
)的原因感到困惑

这是因为
状态
应始终以不变的方式更新。在您的情况下,由于
位于依次位于数组中的对象中,因此
计数器
数组和
计数器
对象在更新后应具有新的引用,以正确地通知React
状态
已更改

在代码段
中,this.setState(counter);
将用
计数器
覆盖状态(因此其他
计数器
将被删除),并且您还将对对象进行变异

如果您想使代码简洁一点,同时确保状态是不可变的,那么这里有一个替代方案:

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

在上面的代码段
map
中,创建一个新的数组,并且
{}
object literal语法创建了一个新的
计数器
对象。

在第二个示例中,您正在使用更新的整数值
计数器
覆盖先前存储在状态中的对象。撇开实践不谈,您的更新方式是否意味着您对状态有不同的结构?@ramesheldy是的,w应该是正确的,我已经更新了我的代码,以显示我在
计数器中传递的内容。这就是我获得命名的地方。@pilchard正确。并且视频片段覆盖了整个状态,而不仅仅是一个对象。这就是我在理解最佳方法时遇到的问题。哦,我明白了,你传递了一个对计数器对象的引用。问题在于,您通过直接更改引用的对象来改变状态。视频中的代码虽然冗长,但通过在状态对象的每个级别上进行克隆(通过扩展运算符)来避免改变状态。感谢您的解释,并非常感谢您的替代方案。
handleDecrement = (counter) => {
  this.setState(prevState => ({counters: prevState.counters.map(c => {
      return (c.id === counter.id && c.value > 0) ? {...c, value: c.value - 1} : c;
  })}));
};