【问题标题】:Can anyone explain why this works with a class component but not a functional component?谁能解释为什么这适用于类组件而不是功能组件?
【发布时间】:2021-03-14 20:13:00
【问题描述】:

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

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

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

功能组件

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 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>
    );
  }
}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您正在对旧数组进行变异,然后使用变异数组设置状态。无论您使用的是类组件还是函数组件,这在 react 中都不是一个好主意。类组件让你侥幸逃脱,但函数组件将之前的状态与之后的状态进行比较,发现它们是同一个数组,因此它跳过了渲染。

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

    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);
    

    【讨论】:

    • 啊哈,这很有道理。谢谢你。您的解决方案效果很好:)
    【解决方案2】:

    您正在更新引用并将相同的引用设置为 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
       };
    

    【讨论】:

    • 感谢您的解释,我很感激。这也很好用!
    猜你喜欢
    • 2019-09-23
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多