如何将道具传递给递归子组件并保留所有道具

时间:2017-02-14 00:18:30

标签: reactjs recursion tree treeview

我遇到了一个有趣的问题。我有一个父组件,它有一个对象数组,它们被传递给一个TreeView的子组件,这意味着它是递归的。我正在向孩子传递一个函数和一些其他道具,以及由孩子递归处理的对象数组。在子项的render函数中记录props时,在第一次渲染时所有的props都在那里,但是当递归函数移动到数组中的每个对象时,它“丢失”所有其他没有递归处理的道具。

当组件首次呈现props对象时:prop1,prop2,arrayOfObjects

当它重新呈现为递归时,子项中的props对象变为:arrayOfObjects。

prop1,prop2已经消失了。

最终结果是我无法从子节点调用父节点中的函数,因此我无法根据单击树中的哪个节点来更新状态。我没有使用redux,因为这是一个样式指南 - 与我们的生产应用程序分开,仅适用于开发人员,而且很简单,所以如果可能的话我想从组件中处理所有状态。

还有一个问题 - 对象数组是我们的styleguide中文件的文件夹结构,我需要能够单击列表中的名称,并使用该文件的内容更新视图。当文件没有任何子节点时,这可以正常工作,但是当有子节点时,如果我单击父节点,则单击该子节点。我已经尝试了e.stopPropagation(),e.​​preventDefault()等但没有运气。提前致谢。

家长:

import React, {Component} from 'react'
import StyleGuideStructure from '../../styleguide_structure.json'
import StyleTree from './style_tree'

class StyleGuide extends Component {

constructor(props) {
    super(props)

    let tree = StyleGuideStructure

    this.state = {
        tree: tree
    }

这是我想从孩子那里打电话的功能

   setVisibleSection(nodeTitle) {

    this.setState({
      section: nodeTitle
    })

   }

   render() {

     return(

     <TreeNode 
      className="class-name-here" 
      setVisibleSection={this.setVisibleSection.bind(this)} 
      node={this.state.tree}
     />

    )

  }
}

 export default StyleGuide

这基本上就是我在孩子身上所做的事情,作为一个小提琴:

https://jsfiddle.net/ssorallen/XX8mw/

唯一的区别是在切换功能中,我试图在父级中调用setVisibleSection,但没有骰子。

这是控制台的照片,显示组件最初渲染时的道具,然后是递归后: enter image description here

1 个答案:

答案 0 :(得分:1)

我认为我真的不明白你的第二个问题。你可以发一个显示问题的小提琴吗?

我认为你的第一个问题是你需要将道具传递给孩子们。我试图把你的例子转录成你的小提琴。您可以通过单击节点看到标题切换到节点的名称。

https://jsfiddle.net/hbjjq3zj/

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string str = value as string;
        int idot = str.IndexOf(".");
        int days = int.Parse(str.Substring(0,idot ));
        int idotdot = str.IndexOf(":"); 
        int ho = int.Parse(str.Substring(idot+1, idotdot-idot-1));
        int newho = days * ho; 
        string res = newho.ToString() + str.Substring(idotdot);
        return res;
    }
/**
 * Using React 15.3.0
 *
 * - 2016-08-12: Update to React 15.3.0, class syntax
 * - 2016-02-16: Update to React 0.14.7, ReactDOM, Babel
 * - 2015-04-28: Update to React 0.13.6
 */

class TreeNode extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
    	visible: true,
    };
  }
  
  toggle = () => {
    this.setState({visible: !this.state.visible});
    this.props.setVisibleSection(this.props.node.title)
  };
  
  render() {
  	var childNodes;
    var classObj;

    if (this.props.node.childNodes != null) {
      childNodes = this.props.node.childNodes.map((node, index) => {
        return <li key={index}><TreeNode {...this.props} node={node} /></li>
      });

      classObj = {
        togglable: true,
        "togglable-down": this.state.visible,
        "togglable-up": !this.state.visible
      };
    }

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

    return (
      <div>
        <h5 onClick={this.toggle} className={classNames(classObj)}>
          {this.props.node.title}
        </h5>
        <ul style={style}>
          {childNodes}
        </ul>
      </div>
    );
  }
}

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
    	visible: true,
    };
  }
  
  toggle = () => {
    this.setState({visible: !this.state.visible});
  };
  setVisibleSection(nodeTitle) {
    this.setState({
      title: nodeTitle
    })
  }
  render() {
    return (
    	<div>
      	Title: {this.state.title}
      	<TreeNode 
        	node={tree} 
          setVisibleSection={this.setVisibleSection.bind(this)}
        />
      </div>
    );
  }
}




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

ReactDOM.render(
  <ParentComponent />,
  document.getElementById("tree")
);