Javascript 更新嵌套状态的替代方法或解决方案

Javascript 更新嵌套状态的替代方法或解决方案,javascript,reactjs,nested,setstate,Javascript,Reactjs,Nested,Setstate,在我的react应用程序中,有一个设置“页面”,其中包含不同的设置类别和相应的设置项目。 因此,我需要一个嵌套状态(?)来避免有很多名为“category1id”、“category1-element1-id”等属性 情况如下: this.state = { categories: [ { id: 1, label: "Category 1",

在我的react应用程序中,有一个设置“页面”,其中包含不同的设置类别和相应的设置项目。 因此,我需要一个嵌套状态(?)来避免有很多名为“category1id”、“category1-element1-id”等属性

情况如下:

    this.state = {
          categories: [
            {
              id: 1,
              label: "Category 1",
              elements: [
                { id: 1, label: "Option 1", selected: true },
                { id: 2, label: "Option 2", selected: false },
              ],
            },
            {
              id: 2,
              label: "Category 2",
              elements: [
                { id: 1, label: "Option 1", selected: true },
                { id: 2, label: "Option 2", selected: false },
                { id: 3, label: "Option 3", selected: false },
              ],
            },
          Other property: "...",
要更新状态,我需要一个深拷贝而不是浅拷贝。我如何做到这一点?是否有其他替代解决方案?

使用

不起作用(错误),也不是真正的防故障

由于这是我的应用程序中唯一的嵌套状态,我希望避免使用lodash&co

单击该选项时调用的函数如下所示。但这直接改变了状态

  handleOptionSelect = (categoryId, option) => {
    const categories = [...this.state.categories];

    // FIND INDEX OF CATEGORY
    const category = categories.find((category) => category.id === categoryId);
    const indexCat = categories.indexOf(category);

    // //FIND INDEX OF ELEMENT
    const elements = [...category.elements];
    const indexEle = elements.indexOf(element);

    //MODIFY COPIED STATE
    const e = categories[indexCat].elements[indexEle];
    e.selected = e.selected ? false : true;

    // //SET NEW STATE
    this.setState({ categories });
  }

非常感谢你的帮助!我还在开始尝试学习React和JS:)

如果使用对象存储类别呢?我的意思是,使用键值的散列,其中每个键都是类别的id

this.state = {
      categories: {
        1: {
          label: "Category 1",
          elements: [
            { id: 1, label: "Option 1", selected: true },
            { id: 2, label: "Option 2", selected: false },
          ],
        },
        2: {...}
      }
}
这将帮助您添加或更新任何类别,例如:

// Update category of id 4
this.setState({...categories, 4: updatedCategory })

如果使用对象存储类别的元素,则相同的原则也应适用于这些元素。

您知道,您只能导入特定的lodash函数,可以只安装一个特定的包,也可以从整个库中导入特定的函数?如果您不想这样做,您只需要在自己的代码中重新创建相同的功能<代码>从“lodash/cloneDeep”导入cloneDeep或。如果你还想自己写,这里有一个答案,列出了所有选项:谢谢,我不知道(我对编程很陌生)!实际上,我在实施您的解决方案时遇到了一些困难。我确实在终端中使用了
npm I lodash.clonedeep
,添加了
import clonedeep from“lodash/clonedeep”
,并替换了
const categories=[…this.state.categories]使用
const categories=\uu.cloneDeep(this.state.categority)
但是我得到一个错误,说“没有定义没有未定义”。我做错了什么?对不起,我的错-我发布的两件事是两种不同的方法。您将使用
import cloneDeep from'lodash/cloneDeep
与整个lodash包结合使用(
npm i lodash
)。它仍然只是导入您指定的模块,但是如果您在其他地方需要它们,您可以导入更多模块
npm i lodash.clonedeep
只安装独立的clonedeep函数,您只需从“lodash.clonedeep”导入
import clonedeep即可使用它。当您想使用它时,您不需要使用前导的
,因为您直接导入了该函数,而不是在名称空间下。谢谢!在这种情况下,我不能使用诸如.map之类的函数来呈现类别,.filter来仅将选定的选项传递给“执行”组件,可以吗?我认为您仍然可以使用
对象.keys
来实现这一点。类似于Object.keys(categories).map(key=>categories[key])
// Update category of id 4
this.setState({...categories, 4: updatedCategory })