reactjs - 在 React 中处理复杂状态的最佳方法

标签 reactjs state

我正在尝试创建一个 react 应用程序,它采用以下数据结构来呈现应用程序...

 var cellTest = [
    {
      type: 'group',
      children: [
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
        {type: 'Cell', name: 'Constitution', abbreviation: 'CON', value: 10},
        {type: 'Cell', name: 'Intelligence', abbreviation: 'INT', value: 10},
        {type: 'Cell', name: 'Wisdom', abbreviation: 'WIS', value: 10},
        {type: 'Cell', name: 'Charisma', abbreviation: 'CHA', value: 10},
      ]
    },
    {
      type: 'group',
      children: [
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
        {type: 'Cell', height: 2, width: 2, name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', height: 2, width: 2, name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', height: 2, width: 2, name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', height: 2, width: 3, name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
      ]
    },
    {
      type: 'group',
      children: [
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
      ]
    },
    {
      type: 'group',
      children: [
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
        {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
      ]
    }, 
  ]

目前,该对象被传递给“Sheet”组件,该组件迭代数组并渲染一个“Group”组件,将所有数据作为 props 向下传递。然后,组组件迭代子数组并使用相应的 props 渲染 Cell 组件。最终,每个单元格将存储必须绑定(bind)到该数据结构的值。我在传递虚拟数据的情况下工作得很好,但是,当我决定尝试连接状态(我对此没什么经验)时,一切都在我面前爆炸了。

如果我单击一个单元格组件并更改一个值,我希望向父组件发送一条消息,该父组件将在状态中容纳“工作表”。该消息将改变状态,从而触发组件的重新渲染(我*认为),从而将更改级联下来。然而,当我这样做时,我遇到了一些奇怪的错误,并且在谷歌搜索后似乎 react 无法处理嵌套数据的状态?

在这种情况下进行状态管理的最佳方法是什么?我应该以某种方式扁平化我的数据吗?

如果这个问题有点模糊,我深表歉意,但是,我的 react 很新,而且让我大吃一惊:)

更新:

作为测试,我尝试简单地向状态添加一个新组,但它失败了。

 let newGroup =     {
    type: 'group',
    children: [
      {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
      {type: 'Cell', name: 'Strength', abbreviation: 'STR', value: 10},
      {type: 'Cell', name: 'Dex', abbreviation: 'DEX', value: 10},
      {type: 'Cell', name: 'Constitution', abbreviation: 'CON', value: 10},
      {type: 'Cell', name: 'Intelligence', abbreviation: 'INT', value: 10},
      {type: 'Cell', name: 'Wisdom', abbreviation: 'WIS', value: 10},
      {type: 'Cell', name: 'Charisma', abbreviation: 'CHA', value: 10},
    ]
  }

  const [sheet, setSheet] = useState(cellTest);

  function addGroup(){
    setSheet(prevSheet => prevSheet.push(newGroup))
  }

这会产生以下错误

TypeError: props.sheet.map is not a function

   8 | console.log('BOOM', props.sheet)
>  9 | let sheet = props.sheet.map((group, index)=>{
     | ^  10 |     // Render each group and pass data within the group as props to that group
  11 |     return <Group key={'Group'+index} {...props.sheet[index]}/>
  12 | })

在我的控制台中,我可以看到由于某种原因,我的 props.sheet 的值(由我的状态传递到的组件读取)现在是整数 5。我什至记录了在击中组件之前传递下来的工作表的值,直到组件尝试读取它为止都没有问题。我唯一能想到的是,由于嵌套状态,React 不知道如何更新我的组件?

最佳答案

为每个单元分配一个 ID。

然后在父元素中编写一个可以获取单元格 ID 和值的方法,然后通过复制所有未更改的数据并将其与包含给定单元格的新值的新对象合并来创建一个新的状态对象。

将该方法作为回调传递给每个单元格,并调用该方法以在更改时更新状态。

您可以使用像 immutability-helper 这样的库帮助进行深度复制。

编辑: 关于您的更新,您的想法是正确的,但是 push()方法将元素添加到数组末尾并返回数组的新长度。而且你不能只添加到现有对象,你需要创建一个新对象,否则React将无法发现更改并且不会重新渲染。

尝试:

addGroup = () => setSheet(prevSheet => [...prevSheet, newGroup]

关于reactjs - 在 React 中处理复杂状态的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62925626/

相关文章:

javascript - 在 react 中单击 anchor 标记后,组件将卸载而不会被调用

javascript - 如何在背景图像 : url()? 上设置授权 header

stream - 如何在 Trident 中映射具有持久状态的元组?

javascript - 在 React 中更新数组

haskell - 自然数序列生成器

css - create-react-app 中的条件 CSS

javascript - 初学者 react : Render Syntax Error

javascript - React 中设置的时间选择器 - jquery-timepicker

PayPal 国家/地区代码

reactjs - 尝试在函数组件之外调用 useContext