简体   繁体   中英

How to manage state in a tree component in reactjs

I've been struggling this for a couple of days, trying to figure out the "react" way to do it.

Basically, I have a tree, a list of lists (of lists ...) that can be arbitrarily nested, and I want a component that will display this and also enable rearrangement.

Here's my data:

var data = [{
      id: 1
    }, {
      id: 2, children: [
        {
          id: 3, children: [{id: 6}]
        }, {
          id: 4
        }, {
          id: 5
        }]
    }]

My first pass was to just have a single "tree" component that builds the nested lists of DOM elements in its render function ( look at the code here ). That actually worked pretty well for small numbers of elements, but I want to be able to support hundreds of elements, and there was a very high re-render cost when an element was moved within the tree (~600ms when there were a few hundred elements).

So I think I'll have each "node" of the tree be it's own instance of this component. But here's my question (sorry for the long intro):

Should each node dynamically query for the list it's children's IDs from a central "database" and store that in state? Or should the top-most node load the whole tree and pass everything down through props?

I'm still trying to wrap my mind around how state & props should be handled & divvied up.

Thanks

I wanted to try out the tree structure with React and came up with a simple component that hides subtrees when you click on <h5> . Everything is a TreeNode . Is this similar to what you were thinking?

You can see it in action in this JSFiddle: http://jsfiddle.net/ssorallen/XX8mw/

TreeNode.jsx :

var TreeNode = React.createClass({
  getInitialState: function() {
    return {
      visible: true
    };
  },
  render: function() {
    var childNodes;
    if (this.props.node.childNodes != null) {
      childNodes = this.props.node.childNodes.map(function(node, index) {
        return <li key={index}><TreeNode node={node} /></li>
      });
    }

    var style = {};
    if (!this.state.visible) {
      style.display = "none";
    }

    return (
      <div>
        <h5 onClick={this.toggle}>
          {this.props.node.title}
        </h5>
        <ul style={style}>
          {childNodes}
        </ul>
      </div>
    );
  },
  toggle: function() {
    this.setState({visible: !this.state.visible});
  }
});

bootstrap.jsx :

var tree = {
  title: "howdy",
  childNodes: [
    {title: "bobby"},
    {title: "suzie", childNodes: [
      {title: "puppy", childNodes: [
        {title: "dog house"}
      ]},
      {title: "cherry tree"}
    ]}
  ]
};

React.render(
  <TreeNode node={tree} />,
  document.getElementById("tree")
);

Seems like it'd be nicer to pass everything down as props, as this will prevent you from the trouble of managing individual insertion/deletion. Also, like the comments said, the key attributes prevents a huge chunk of unnecessary re-rendering.

You might want to check this link: http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html . It describes the kind of dilemma you're having and how to approach it.

(Coincidentally, I've made a react tree view a while ago: https://github.com/chenglou/react-treeview . Take whatever you want from it!)

Here is a quick example of how to create a treeview using React and Flux. http://www.syntaxsuccess.com/viewarticle/5510d81be1ce52d00e93da55

The React component is recursive and state is managed using Flux.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM