从React.js中递归呈现的组件更新状态

问题描述 投票:1回答:2

我需要从递归呈现的组件中以React状态更新深层嵌套的对象。这些项目看起来像这样,可以动态嵌套:

const items = [
  {
    id: "1",
    name: "Item 1",
    isChecked: true,
    children: []
  },
  {
    id: "3",
    name: "Item 3",
    isChecked: false,
    children: [
      {
        id: "3.1",
        name: "Child 1",
        isChecked: false,
        children: [
          {
            id: "3.1.1",
            name: "Grandchild 1",
            isChecked: true,
            children: []
          },
          {
            id: "3.1.2",
            name: "Grandchild 2",
            isChecked: true,
            children: []
          }
        ]
      },
      {
        id: "3.2",
        name: "Child 2",
        isChecked: false,
        children: []
      }
    ]
  }
]

我在解决如何从深层嵌套的组件中更新顶级状态时遇到问题,因为它仅“了解”自身,而不是整个数据结构。

class App extends React.Component {
  state = {
    items
  };

  recursivelyRenderItems(items) {
    return (
      <ul>
        {items.map(item => (
        <li key={item.id}>
          {item.name}
          <input type="checkbox" checked={item.isChecked} onChange={(event) => {
            // TODO: Update the item's checked status
          }} />
          {this.recursivelyRenderItems(item.children)}
        </li>
    ))}
      </ul>

    )
  }

  render() {
    return (
      <div>
        {this.recursivelyRenderItems(this.state.items)}
      </div>
    );
  }
}

请问我该如何实现?

javascript reactjs recursion immutability
2个回答
0
投票

如何:

创建具有两个参数的updateState函数:idnewState。由于ids已经告诉您要更新的项目:3, 3.1, 3.1.1,因此您可以从任何递归项目中使用要修改的项目的id来调用更新功能。用点将id分开,然后递归扔出您的物品以找出合适的物品。

例如,从递归渲染项目3.1.1中,可以这样调用updateStateupdateState('3.1.1', newState)


0
投票

这对您发布的小提琴有效。

[基本上,每个组件都需要了解其item.isChecked和其父级的isChecked。因此,创建一个包含2个props的组件,itemparentChecked,其中后者是父对象的布尔值,前者成为构造函数中的可变状态变量。

然后,该组件仅在事件处理程序中更新其检查状态,并且全部在render方法中向下流动:

import React from "react";
import { render } from "react-dom";
import items from "./items";

class LiComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      item: props.item
    }
  }

  render() {
    var t = this;
    return (
      <ul>
            <li key={t.state.item.id}>
              {t.state.item.name}
              <input
                type="checkbox"
                checked={t.state.item.isChecked || t.props.parentChecked}
                onChange={event => {
                  t.setState({item: {...t.state.item, isChecked: !t.state.item.isChecked}})
                }}
              />
            </li>
            {t.state.item.children.map(item => (
              <LiComponent item={item} parentChecked={t.state.item.isChecked}/>
            ))}
      </ul>
    );
  }
}
class App extends React.Component {
  state = {
    items
  };

  render() {
    return (
      <div>
        {this.state.items.map(item => (
        <LiComponent item={item} parentChecked={false} />
        ))}
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

https://codesandbox.io/s/treelist-component-ywebq

© www.soinside.com 2019 - 2024. All rights reserved.