【问题标题】:How can I use setState() to modify a multidimensional array in React Native?如何使用 setState() 修改 React Native 中的多维数组?
【发布时间】:2020-01-10 15:16:55
【问题描述】:

我目前正在尝试将 React 组件添加到我的多维数组的第三层。我的结构如下:

constructor(props) {
        super(props);

        /**
         * The state variables pertaining to the component.
         * @type {Object}
         */
        this.state = {
            structure : [ // Block
                [ // Slot 1
                    [ // Layer 1
                        <Text>text 1</Text>, // Text1
                    ]
                ]
            ],
        };
}

this.state.structure 包含slots 的数组,其中包含layers 的数组,其中包含由Text 组件组成的数组。

我尝试同时使用concat()push() 来设置structure 数组,但都给我错误,例如“无法读取未定义的属性”等。这是我当前的addText()功能:

addText() {
        this.setState((previousState) => ({
            structure : previousState.structure[0][0].concat(<Text>text2</Text>),
        }));
}

在我的应用程序中按下按钮时会调用addText() 函数。

我还直接通过数组在当前层渲染我的Text 组件数组:

{ this.state.structure[0][0] }

我觉得我直面问题,但不知道是什么导致了问题。我希望能够将另一个 Text 添加到容器中,但我尝试做的任何事情似乎都不起作用。

【问题讨论】:

    标签: javascript arrays typescript react-native multidimensional-array


    【解决方案1】:

    没有深入探讨是否应该按照自己的方式做事的哲学,根本问题是您在您的州将structure 替换为structure[0][0]

    {
      // this line sets the whole structure to structure[0][0]:
      structure : previousState.structure[0][0].concat(<Text>text2</Text>),
    }
    

    【讨论】:

      【解决方案2】:

      我不同意这个 arr 结构和钩子,一个对象似乎更传统,但它可能是你的 this 绑定。正如雷所说的结构[0] [0]正在替换状态。 如果您使用 addText 方法,则需要将其绑定到该类。如果它不使用箭头语法,它将显示为未定义,因为它未绑定,并将导致未定义。希望对你有帮助

      例如

         class App extends React.Component {
      
      
      constructor(props) {
          super(props);
          this.state = {
            value: '',
          };
          this.addText = this.addText.bind(this);
        }
        addText() {
              this.setState((previousState, props) => ({
                  structure : previousState.structure[0][0].concat(<Text>text2</Text>),
              }));
      }
      // ES6
        addTextEs6 = () => {
          this.setState((previousState, props) => ({
            structure : previousState.structure[0][0].concat(<Text>text2</Text>),
        }));
        } 
      }
      
      //ES6 
      /* Also you do not need to use concat you can use the spread Op. ... See MDN Spread Op`
      

      【讨论】:

      • 这仍然包括原来的问题,即structure 被完全替换为structure[0][0]
      【解决方案3】:

      一方面,您确实应该将 React 组件的实例直接存储在 state 中。这样做只是自找麻烦,因为渲染、状态更新、key 管理和数据持久性变得越来越难以解决。

      相反,将组件的 模型 存储在 state 中,通常以它们应该具有的道具的形式。然后,在渲染时是将这些模型转换为 React 组件的时间:

          this.state = {
              structure : [ // Block
                  [ // Slot 1
                      [ // Layer 1
                          "text 1", // Text1
                      ]
                  ]
              ],
          };
      
          render() {
              return this.state.structure[0][0].map(ea => <Text key={ea}>{ea}</Text>);
          }
      

      这样做会更好,因为:如果您想读取或修改“层”数组的内容会发生什么?如果它们是文本值,您可以简单地读取/修改文本。但是如果它们是实例化的 React 组件......基本上没有办法在不经过大量循环的情况下有效地更新你的状态。

      关于您的具体问题:问题是当您评估这样的陈述时:

      previousState.structure[0][0].concat(<Text>text2</Text>)
      

      concat() 函数实际上返回串联后数组的值。该数组的值(在这种情况下)现在是[&lt;Text&gt;text 1&lt;/Text&gt;, &lt;Text&gt;text2&lt;/Text&gt;]。因此,您实际上是将state.structure 字段的值更新为一个完全不同的数组。我猜你看到的错误 - “无法读取未定义的属性” - 是因为当你尝试访问 this.state.structure[0][0] 时,你正试图访问它,就好像它是一个二维数组,但它现在实际上是一个维数组。

      正如另一位回复者所说的更简洁:您将 state.structure 完全替换为 state.structure[0][0] 的内容(连接后)。

      在 React 状态下更新深度嵌套的数据结构非常棘手。您基本上想要复制所有原始数据结构并仅更改其中的一部分。幸运的是,with ES6 "spread" operator 我们有一个简写方式来创建包含所有相同项以及新项的新数组:

      addText() {
          this.setState((previousState) => {
              // Copy the old structure array
              const newStructure = [...previousState.structure];
              // Update the desired nested array by copying it, plus a new item
              newStructure[0][0] = [...newStructure[0][0], "text2"];
      
              this.setState({structure: newStructure});
          });
      }
      

      主要内容:

      1. 不要在状态中存储 React 组件!存储原始数据并在渲染时使用。
      2. 注意将 state 更新为的内容 - 它必须是相同的状态加上一些更新,而不是某些原子操作的结果。
      3. 稍微了解一下concat()push() 等数组操作的实际工作原理以及它们的返回值。

      【讨论】:

      • 绝对精彩的答案!它完美地解决了我的问题。我必须感谢你给了我关于在我的组件状态中存储哪些类型的数据的提示;这是我在其他一些组件上犯的错误,但在修复它们之后,我注意到性能也发生了巨大变化。非常感谢,@jered。
      • @Gumptastic 乐于助人:)
      猜你喜欢
      • 1970-01-01
      • 2019-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 2016-07-29
      • 2023-02-26
      相关资源
      最近更新 更多