繁体   English   中英

谁能解释为什么这适用于 class 组件而不是功能组件?

[英]Can anyone explain why this works with a class component but not a functional component?

基本上,我有几个按钮。 我希望用户能够选择多个按钮。

我尝试使用功能组件并将按钮 state 存储为带有 useState 挂钩的 object。 当点击按钮时,state 会相应更新,但按钮的道具不会更新。 当 props.isActive 发生变化时,我尝试使用 useEffect 重新渲染组件,但这不起作用。

使用 class 组件,这完全符合预期。 我只是想了解为什么会这样。 如果有人能提供见解,我将不胜感激。 谢谢。

功能组件

const View = (props) => {
  var [buttons, setButtons] = useState([
    { name: "Small", isActive: false },
    { name: "Large", isActive: false },
  ]);
  const handleClick = (index) => {
    let tmp = buttons;
    tmp[index].isActive = !tmp[index].isActive;
    return setButtons(tmp);
  };
  return (
      <div>
            {buttons.map((e, index) => {
              return (
                <MyButtonComponent
                  key={index}
                  name={e.name}
                  isActive={e.isActive}
                  onClick={() => handleClick(index)}
                />
              );
            })}
    </div>
  );
};

Class 组件

class View extends Component {
  state = {
    btn: [
      { name: "Small", isActive: false },
      { name: "Large", isActive: false },
    ],
  };
  handleClick = (index) => {
    let tmp = this.state.btn;
    tmp[index].isActive = !tmp[index].isActive;
    return this.setState({ ...this.state, btn: tmp });
  };
  render() {
    return (
            <div>
              {this.state.btn.map((e, index) => {
                return (
                  <MyButtonComponent
                    key={index}
                    name={e.name}
                    isActive={e.isActive}
                    onClick={() => this.handleClick(index)}
                  />
                );
              })}
            </div>
    );
  }
}

您正在对旧数组进行变异,然后使用变异数组设置 state 。 无论您使用的是 class 组件还是 function 组件,这在反应中都不是一个好主意。 class 组件让您侥幸逃脱,但 function 组件将 state 之前的状态与之后的状态进行比较,并看到它们是相同的渲染数组。

要解决此问题,您应该创建一个新的 state 而不是改变旧的。 改变这个:

let tmp = buttons;
tmp[index].isActive = !tmp[index].isActive;
return setButtons(tmp);

对此:

// Create a copy of the array
let tmp = [...buttons]; 
// Also copy the item you want to change
tmp[index] = {
  ...tmp[index],
  active: !tmp[index].active
}
setState(tmp);

您正在更新引用并将相同的引用设置为 state (setButtons(tmp)) ,它react thinks ,由于浅比较,数组没有改变。 您需要使用新的参考。 像下面这样

    let tmp = buttons; <-- problem is here, reference 
    tmp[index].isActive = !tmp[index].isActive;
    return setButtons(tmp); <-- and updating same `reference`
   const handleClick = (index) => {
     buttons[index].isActive = !buttons[index].isActive;
     return setButtons([...buttons]); <-- this will work
   };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM