嵌套对象的状态更新方法问题

如何解决嵌套对象的状态更新方法问题

主要编辑

我有一个非常大的物体,深度为 3 级。我使用它作为模板在页面生成组件并存储稍后使用的值,例如:

obj =
 { 
  "group": {
    "subgroup1": {
      "value": {
        "type": "c","values": []
      },"fields_information": {
        "component_type": "table","table_headers": [
          "label","size"
        ],}
    },"subgroup2": {
      "value": {
        "type": "c",},}

多亏了这一点,我可以动态生成视图,该视图作为模板存储在数据库中。

我正在为两件事而苦苦挣扎。首先,根据用户输入的文本框、复选框等更新值。 我是这样做的:

    const updateObj = (group,subgroup,value) => {
        let tempObj = {...obj}
        tempObj[group][subgroup].value.value = value
        toggleObj(tempObj)
    }

我知道扩展运算符实际上并没有进行深复制。但是,它允许我处理对象并稍后保存。这是一个问题吗?我是否必须 cloneDeep 或者它很好? cloneDeep 会影响性能吗?

下面描述第二种情况

export const ObjectContext = React.createContext({
    obj: {},toggleObj: () => {},});

export const Parent = (props) => {
    const [obj,toggleObj] = useState()
    const value = {obj,toggleObj}

    return (
        <FormCreator />
    )
}

const FormCreator = ({ catalog }) => {
    const {obj,toggleObj} = React.useContext(ObjectContext)

    return (<>
        {Object.keys(obj).map((sectionName,sectionIdx) => {
        const objFieldsinformation = sectionContent[keyName].fields_information
        const objValue = sectionContent[keyName].value
        ...
            if (objFieldsinformation.component_type === 'table') {
            return (
                <CustomTable 
                key={keyName + "id"}
                label={objFieldsinformation.label}
                headers={objFieldsinformation.table_headers}
                suggestedValues={[{label: "",size: ""},{label: "",size: ""}]}
                values={objValue.values}
                sectionName={sectionName}
                keyName={keyName}/>
            )
            }
        ...
        })}
    </>)
}

const CustomTable= (props) => {
    const { label = "",headers = [],suggestedValues = [],values,readOnly = false,sectionName,keyName } = props
    const {obj,toggleObj} = React.useContext(ObjectContext) 
    
    //this one WORKS
    useEffect(() => {
        if (obj[sectionName][keyName].value.type === "complex") {
            let temp = {...obj}
            temp[sectionName][keyName].value.values = [...suggestedValues]
            toggleObj(temp)
        }
    },[])
    
    //this one DOES NOT
    useEffect(() => {

        if (obj[sectionName][keyName].value.type === "c") {
            let temp = {...obj,[sectionName]: {...obj[sectionName],[keyName]: {...obj[sectionName][keyName],value: {...obj[sectionName][keyName].value,values: [{label: "",size: ""}]}}}}
            toggleObj(temp)
        }
    },[])
    
    return (
    //draw the array
    )
}

请参考 CustomTable 组件。 与上面的示例对象一样,我有 2 个要打印的自定义表。不幸的是,一个应该工作的 useEffect 工作不正常。我正在观察,该值字段仅针对 Obj 中的最后一个“表”设置。当我做 obj 的浅拷贝时,它工作正常。但我担心将来可能发生的任何影响。

我对使用 createContext 也完全陌生,也许这就是问题所在。

感谢任何理解这种混乱的人:)

解决方法

主要问题似乎是您没有提供您的上下文。你所拥有的是字面上传递空白对象和 void 返回函数。因此为什么调用它没有实际效果,但改变值却有。

export const ObjectContext = React.createContext({
    obj: {},toggleObj: () => {},});

export const Parent = (props) => {
    const [obj,toggleObj] = useState({})
    const value = {obj,toggleObj}

    return (
        <ObjectContext.Provider value={value}>
           <FormCreator />
        </ObjectContext.Provider>
    )
}

理想情况下,您还可以让上述组件环绕 FormCreator 并将其呈现为 props.children。这是为了防止每次调用 toggleObj 时都重新渲染整个子树。请参阅 first part of this tutorial 以了解典型模式。

关于改变状态的问题,在 React 中保持状态不可变是绝对重要的——至少,如果你正在使用 useState 或某种减速器。 Stack Overflow 上经常会出现由状态突变引起的错误,事实上我最近做了一个 codesandbox 来演示一些更常见的错误。

我也同意@SamuliHakoniemi 的观点,像这样的深度嵌套对象实际上更适合 useReducer 钩子,甚至可能更进一步并建议这里需要像 Redux 这样的适当状态管理库。它将允许您细分 reducer 以针对实际更新的状态片段,这将有助于在深度克隆状态结构成为实际问题时降低性能成本。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?