javascript - 如何在不使用 Flux 的情况下将状态从深层节点传播到嵌套树的根?

标签 javascript reactjs

我正在渲染一个嵌套的评论树,我无法弄清楚如何从深度嵌套的评论之一更新评论容器中存在的树数据。我创建了一个代表该场景的基本 fiddle ,请查看 HERE 。每个节点中的按钮应该反转“likes”属性的值,该值应该来自父容器中的状态。寻找非 redux 解决方案。

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tree: [
        {
          id: "cake",
          likes: true,
          kids: [
            {
              id: "banana",
              likes: false,
              kids: []
            },
            {
              id: "rocket",
              likes: false,
              kids: [
                {
                  id: "homework",
                  likes: true,
                  kids: [
                    {
                      id: "something",
                      likes: true,
                      kids: []
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    };
  }

  render() {
    return (
      <div>
        {this.state.tree.map(value => <Kid value={value} />)}
      </div>
    );
  }
}

class Kid extends React.Component {
  render() {
    return (
      <div style={{margin: '20px', border: '5px dashed #DCEDC8'}}>
        <span>id: {this.props.value.id}</span><br />
        <span>likes: {this.props.value.likes ? 'yes' : 'no'}</span><br />
        <button>invert</button>
        {this.props.value.kids.length
          ? this.props.value.kids.map(value => <Kid value={value} />)
          : null}
      </div>
    );
  }
}

React.render(<Parent />, document.getElementById("container"));
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

最佳答案

对 Redux 状态的建议是保持其标准化,如下所示:

this.state = {
  normalized: [
    cake: {likes: true, kids: ["banana", "rocket"]}
    banana: {likes: false, kids: []},
    rocket: {likes: false, kids: ["homework"]},
    homework: {likes: true, kids: ["something"]},
    something: {likes: true, kids: []},
  ],
  root: "cake",
};

然后,如果您有 id,则可以使用 this.state.normalized[id] 引用一个项目

例如,要遍历树并对每个节点应用函数,您可以这样做:

function traverse(node, func) {
  func(node);

  for (let i = 0, len = node.kids.length; i < len; i++) {
    traverse(this.state.normalized[node.kids[i]]);
  }
}

traverse(this.state.normalized[this.state.root]);

如果您不想编写自己的解决方案,Normalizr 对于标准化嵌套 API 响应非常有用。

如果你真的想在你的状态中保留一棵不可变的树,Immutable.js 擅长让你在一行中高效地改变树而不改变它。

关于javascript - 如何在不使用 Flux 的情况下将状态从深层节点传播到嵌套树的根?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43423833/

相关文章:

javascript - 动态创建React组件

javascript - $scope.$watch 使用 Angular 和 Ionic/Cordova 的 div 标签

javascript - 警告: Prop 类型失败:提供给“提供者”的对象类型为“对象”的 Prop child 无效,需要一个ReactElement

javascript - useEffect 中的简单事件监听器导致多个警告

node.js - 当事先不知道图像名称时,将图像导入到 React.js 中的 <src> 标记中

javascript - 如何覆盖 Material 表中的 MuiPaper-root 样式

reactjs - Material-UI 主题不会变回来

javascript - 私有(private) AND 静态 AND 继承变量!?或类似

javascript - 设置间隔变化?

javascript - 如何在 JavaScript 的数组列表中找到最大的数组值