【问题标题】:React setting state in useState hook在 useState 钩子中反应设置状态
【发布时间】:2020-11-30 08:29:54
【问题描述】:

我在使用 useState 挂钩更新状态时遇到问题。
所以在我的“App”组件中,我声明了我的对象数组状态:

const [panelSettings, setPanelSettings] = useState([
{
  title: 'Background',
  active: true,
  options: [],
  updateDaily: true
},
{
  title: 'Time and Date',
  active: true,
  showSeconds: true
},
{
  title: 'Weather Forecast',
  active: false,
  city: null
}])

然后我将{panelSettings}{setPanelSettings} 传递给另一个组件,我们称之为“菜单”。
在这个“菜单”组件中,我呈现每个标题并在它们旁边有一个复选框,它应该设置“活动”属性。像这样:

{panelSettings.map(element => {
   return (
     <div key={element.title}>
       {element.title}
       <input type='checkbox' checked={element.active} onChange={() => setPanelSettings(element.active = !element.active)} />
     </div>)
})}

但是当我点击任何复选框时,我会收到错误“TypeError: Cannot read property 'active' of undefined”。但是,它来自我的父组件(“应用程序”),而不是来自“菜单”。
我尝试了多种方法来渲染元素并调用setPanelSettings 函数,但到目前为止没有任何效果。我还从“菜单”组件中注销了该对象,似乎“活动”属性在那里发生了变化。

【问题讨论】:

  • 你可以参考这个。我相信它涵盖了您的情况:stackoverflow.com/questions/55823296/…。 useState 不会合并对象的所有值。
  • 你能看到标题吗?
  • 是的,在我点击其中一个复选框之前一切正常

标签: javascript reactjs react-hooks use-state


【解决方案1】:

当你这样做时

setPanelSettings(element.active = !element.active)

你将panelSettings

[{
  title: 'Background',
  active: true,
  options: [],
  updateDaily: true
},
{
  title: 'Time and Date',
  active: true,
  showSeconds: true
},
{
  title: 'Weather Forecast',
  active: false,
  city: null
}]

发送至truefalse。显然不是你想要的。

可能你想这样做:

setPanelSettings((prevState) => prevState.map((s) => {
    if (s === element) {
        return { ...s, active: !s.active };
    }
    return s;
}))

【讨论】:

  • 只是我的一个侧面评论,这可以工作,但它不使用以前的状态?
【解决方案2】:

您究竟从哪里得到错误?是来自 onChange 函数还是来自 checked 属性? 如果是在onChange函数中,就得用之前的状态来更新新的状态,所以应该是这样的:

setPanelSettings((prevState) => {
   return prevState.map((menuInput) => {
       if (menuInput.title === element.title)
          return { ...menuInput, active: !menuInput.active };

       return menuInput;
   });
})

【讨论】:

    【解决方案3】:

    cmets 让我走上了正轨,最终的解决方案是这样的:

    {panelSettings.map(element => {
      return (
        <div key={element.title}>
          {element.title}
          <input type='checkbox' checked={element.active} onChange={() => {
            const next = [...panelSettings];
            next[index].active = !next[index].active;
            setPanelSettings(next);
          } />
        </div>)
    })}
    

    我确定这不是最复杂的,但我真的不知道如何以更简洁的方式解决它并完成工作。所以谢谢大家的回答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-22
      • 2020-04-19
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多