简体   繁体   English

在 useState 钩子中反应设置 state

[英]React setting state in useState hook

I have problem with updating my state using useState hook.我在使用 useState 挂钩更新 state 时遇到问题。
So in my "App" component, I declare my array of objects state:所以在我的“App”组件中,我声明了我的对象数组 state:

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

Then I pass {panelSettings} and {setPanelSettings} down to another component, let's call it "Menu".然后我将{panelSettings}{setPanelSettings}传递给另一个组件,我们称之为“菜单”。
In this "Menu" component I render each title and have a checkbox next to them, which should set the "active" property.在这个“菜单”组件中,我呈现每个标题并在它们旁边有一个复选框,它应该设置“活动”属性。 Like so:像这样:

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

But when I click on any of the checkboxes, I get the error "TypeError: Cannot read property 'active' of undefined" .但是,当我单击任何复选框时,我收到错误"TypeError: Cannot read property 'active' of undefined" However, it comes from my parent component ("App") and not from the "Menu".但是,它来自我的父组件(“App”),而不是来自“菜单”。
I've tried multiple ways to render out the elements and calling the setPanelSettings function but nothing has worked so far.我尝试了多种方法来渲染元素并调用setPanelSettings function 但到目前为止没有任何效果。 I've also logged out the object from the "Menu" component and it seemed like the 'active' property has changed there.我还从“菜单”组件中注销了 object,看起来“活动”属性在那里发生了变化。

When you do当你这样做

setPanelSettings(element.active = !element.active)

you are changing panelSettings from您正在更改panelSettings

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

to either true or false .truefalse Clearly not what you want.显然不是你想要的。

Probably you want to do:可能你想做:

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

Where exactly do you get the error?你到底在哪里得到错误? Is it from the onChange function or from the checked attribute?是来自 onChange function 还是来自选中的属性? If it is in the onChange function, you have to use the previous state to update the new state, so it should be something like this:如果是在onChange function 中,则必须使用之前的state 来更新新的state,所以应该是这样的:

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

       return menuInput;
   });
})

The comments put me on the right track, and the final solution was this:评论让我走上了正轨,最终的解决方案是:

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

I'm sure it's not the most sophisticated, but I don't really know how it could be solved in a more concise way and it got the job done.我确信它不是最复杂的,但我真的不知道如何以更简洁的方式解决它并完成工作。 So thanks everyone for the answers.所以感谢大家的回答。

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

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