ES6/React:为啥我的三重嵌套 setState 更新不起作用?

Posted

技术标签:

【中文标题】ES6/React:为啥我的三重嵌套 setState 更新不起作用?【英文标题】:ES6/React: Why is my triple-nested setState update not working?ES6/React:为什么我的三重嵌套 setState 更新不起作用? 【发布时间】:2018-07-05 08:09:41 【问题描述】:

我有一个包含三个嵌套属性的状态对象,我一次只需要更新值。所以我使用 ES6 扩展语法来更新状态,但由于某种原因,每当我运行它时,它都会给我未定义的属性类型错误。

当我只有两个嵌套属性时,它工作得很好。有什么问题?

method(type, row, col) 
        this.setState(
            changedCells: 
                ...this.state.changedCells,
                [type]: 
                    ...this.state.changedCells[type],
                    [row]: 
                        ...this.state.changedCells[type][row],
                        [col]: true
                    
                
            
        

当 changedCells 状态最初为空时。而setState方法是这样的,用星号表示,运行良好。但是在我的第一个示例中,cellState 为空,并且 type='wood', row=0, col=0,它不起作用但在第二个示例中有效。

method(type, row, col) 
        this.setState(
            changedCells: 
                ...this.state.changedCells,
                [type]: 
                    ...this.state.changedCells[type],
                    [row]: 
                        ...this.state.changedCells[row], ***CHANGED***
                        [col]: true
                    
                
            
        

【问题讨论】:

你的状态初始值是多少? this.state.changedCells[type] 保证存在吗?如果不是,this.state.changedCells[type][row] 总是会抛出,无论合并逻辑如何。 @AlexYoung 初始状态是changedCells是空的。 @loganfsmyth 应该保证存在。嗯,当我只做了一个关联 [index] 之前,我对代码没有任何问题,偶然有 ...this.state.changedCells[row] 而不是 ...this.state.changedCells[type][row]。所以我想这是导致问题的原因。为什么会这样?您建议如何解决? 为了给你一个真正的答案,我们需要一个可运行的实际功能示例。 setState 等在这里无关紧要。删除它们并显示changedCells 的示例以及导致错误的typerowcol 示例。 【参考方案1】:

假设你的初始状态是:

this.state = 
    changedCells: 
;

然后您的属性访问评估如下:

this.state.changedCells 计算结果为

this.state.changedCells[type] 计算结果为未定义

this.state.changedCells[type][row]TypeError: 无法读取未定义的属性行

您的代码以前可以工作,因为您可以在 undefined 上使用扩展运算符:

...undefined === 

您可以通过两种方式解决您的问题。要么初始化状态以包含它需要的每个 typerow,例如

this.state = 
    changedCells: 
        typeA: 
            row1: 
                col1: false
            
        
    

等等。如果您有一组明确定义的类型、行和列,这很好,但如果您有很多类型或事先不知道它们的名称,则不切实际。

另一个选项是在对象可能未定义时提供默认的空对象:

method(type, row, col) 
    this.setState(
        changedCells: 
            ...this.state.changedCells,
            [type]: 
                ...this.state.changedCells[type],
                [row]: 
                    ...(this.state.changedCells[type] || )[row],
                    [col]: true
                
            
        
    

有一些工具可以让您的生活更轻松。您可以使用 lodash get 检索属性,提供默认值。

method(type, row, col) 
    this.setState(
        changedCells: 
            ...(_.get(this.state, "changedCells", )),
            [type]: 
                ...(_.get(this.state, ["changedCells", type], )),
                [row]: 
                    ...(_.get(this.state, ["changedCells", type, row], )),
                    [col]: true
                
            
        
    

【讨论】:

您的第二个选项(默认空对象)效果很好!感谢您的详细解释。它帮助我理解了我的问题并教会了我一些新东西。我会安装那个不变性助手! 我删除了那部分答案,因为它实际上不适用于您的情况。哎呀。尽管如此,它还是一个非常有用的库! 是的,刚试过,不行。不过,感谢您提供出色的分步解释和回答。

以上是关于ES6/React:为啥我的三重嵌套 setState 更新不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

使用 normalize 展平三重嵌套 JSON

导轨中的三重嵌套模型形式显示错误

递增循环是 R 中三重嵌套循环的正确方式

如何正确转义 JSP 标记中的三重嵌套引号

如果子关系在 Laravel 中有结果,我如何只返回父级,如果关系是三重嵌套的?

为啥我的 graphql 嵌套查询返回 null?