推送JSX元素作为Array中另一个JSX元素的子元素(ReactJS)

时间:2017-04-24 17:52:37

标签: javascript reactjs

我正在编写一个反应应用程序,用于从嵌套对象数组中打印树视图。每个节点都应该是可折叠的(默认情况下是打开的)。节点可以具有任意数量的子节点。以下是我想要实现的一个示例:

Tree View

我正在收集数组中的所有节点组件,然后在render方法中访问该集合。现在,所有节点组件都以相同的层次结构打印,因为它们没有相互嵌套。在下面的代码中,如何在<PrintNode treeData={obj}数组中添加<PrintNode treeData={obj} hasChildNodes={true} />作为treeToRender的孩子?

App.js:

import React from 'react';
import PrintNode from './components/PrintNode';

export default class App extends React.Component {
  data = [ // this data will come from another file in real app
    {
      text: 'Parent 1',
      nodes: [
        {
          text: 'Child 1',
          nodes: [
            {
              text: 'Grandchild 1'
            },
            {
              text: 'Grandchild 2'
            }
          ]
        },
        {
          text: 'Child 2'
        }
      ]
    },
    {
      text: 'Parent 2'
    },
    {
      text: 'Parent 3'
    },
    {
      text: 'Parent 4'
    },
    {
      text: 'Parent 5'
    }
  ];

  treeToRender = [];

  getNextNode(nextData) {
    let key = 0;
    for (let i = 0; i < nextData.length; i++) {
      let obj = nextData[i];
      if (!obj.nodes) {
        this.treeToRender.push(<PrintNode treeData={obj} />)
        key++;
      }
      else {
        this.treeToRender.push(<PrintNode treeData={obj} hasChildNodes={true} />)
        key++;
        this.getNextNode(obj.nodes);
      }
    }
    return this.treeToRender;
  }

  render() {
    return (
      <div className="app-container">
        {this.getNextNode(this.data)}
      </div>
    );
  }
}

PrintNode.js

import React from 'react';

export default class PrintNode extends React.Component {
    render() {
        let nodeToRender = '';
        if (this.props.hasChildNodes) {
            nodeToRender = <div className="has-child">{this.props.treeData.text}</div>
        }
        else {
            nodeToRender = <div>{this.props.treeData.text}</div>
        }
        return (
            <div>
                <div>{this.props.treeData.text}</div>
            </div>
        );
    }
}

请注意,每个JSX元素都是一个对象,而不是一个可以轻松操作的字符串。

此外我收到错误“数组或迭代器中的每个子节点都应该有一个唯一的”key“prop。检查App的渲染方法。”即使我已经为PrintNode添加了密钥。为什么会这样?

这是fiddle

1 个答案:

答案 0 :(得分:4)

这是一个更新的解决方案。我希望这有助于您了解如何递归构建JSX对象。

我也提供了一个Codepen供您查看,以便您可以看到正常工作的代码。

function createTree(data) {
    return (
        <ul>
            {
                data.map((node) => {
                    return createNode(node);
                })
            }
        </ul>
    );
}

function createNode(data) {
    if (data.nodes) {
        return (
      <li>
        <PrintNode text={ data.text }>{createTree(data.nodes)}</PrintNode>
      </li>
    );
    } else {
        return <PrintNode text={ data.text } />
    }
}

const PrintNode = (props) => {
    return <li>{ props.text }{ props.children }</li>
};

const App = (props) => {
    return createTree(props.data);
}

ReactDOM.render(<App data={ data } />, document.getElementById("app"));

const data = [
    {
        text: 'Parent 1',
        nodes: [
            {
                text: 'Child 1',
                nodes: [
                    {
                        text: 'Grandchild 1'
                    },
                    {
                        text: 'Grandchild 2'
                    }
                ]
            },
            {
                text: 'Child 2'
            }
        ]
    },
    {
        text: 'Parent 2'
    },
    {
        text: 'Parent 3'
    },
    {
        text: 'Parent 4'
    },
    {
        text: 'Parent 5'
    }
];