Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用useState将子级添加到树中_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 使用useState将子级添加到树中

Javascript 使用useState将子级添加到树中,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我有一个简单的带有React的树,该树有来自根节点的数据,它递归地呈现其子节点- <div className="Tree"> <div>{props.name}</div> <div className="children"> {props.children && props.children.map((item) => { return &

我有一个简单的带有React的树,该树有来自根节点的数据,它递归地呈现其子节点-

<div className="Tree">
  <div>{props.name}</div>
  <div className="children">
    {props.children &&
      props.children.map((item) => {
        return <TreeNode name={item.name} children={item.children} />;
      })}
  </div>
</div>
通过更改TreeNode组件并使用useState,我如何为向树中的任何节点添加子节点的操作设置选项

这是我目前掌握的代码-


您可以在按钮中实现添加子项的操作,并为新子项指定您想要的任何名称

这是一个演示。我将每个子节点存储在父节点的组件状态中。输入显示单击“添加”时创建的节点的名称


这是一个演示。我将每个子节点存储在父节点的组件状态中。输入显示单击“添加”时创建的节点的名称

一种方法是复制处于内部状态的props.children并向其中添加新的子级:

一种方法是复制处于内部状态的props.children并向其中添加新的子级:


在您的示例中,您渲染了一个独立的TreeComponent,但您希望将树作为状态保存在上面的级别。您还应该将键应用于映射的元素,以便在状态更改时只重新渲染必要的内容。关于一个有效的递归示例,请参见此答案:在您的示例中,您呈现了一个独立的TreeComponent,但您希望将树保持为上面级别的状态。您还应该将键应用于映射的元素,以便在状态更改时只重新渲染必要的内容。请参阅此答案,了解一个有效的递归示例:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

const TreeNode = (props) => {
  const [children, setChildren] = useState([]);
  const [input, setInput] = useState(props.name + "-0");

  function addNode(e) {
    e.preventDefault();
    setChildren((children) => [...children, { name: input, children: [] }]);
    setInput(`${props.name}-${children.length + 1}`);
  }

  return (
    <div className="Tree">
      <div>
        <span>{props.name}</span>
        <form onSubmit={addNode}>
          <input
            type="text"
            value={input}
            onChange={(e) => setInput(e.target.value)}
          />
          <button type="submit">Add child</button>
        </form>
      </div>
      <div className="children">
        {children &&
          children.map((item, index) => {
            return <TreeNode key={index} name={item.name} />;
          })}
      </div>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<TreeNode name="Node" />, rootElement);

const TreeNode = (props) => {
  const [childState, setChildState] = useState(props.children);
  const addChild = () => {
    setChildState((childState) => {
      return [
        ...(childState || []),
        { name: `${props.name}-${childState?.length + 1 || 1}` }
      ];
    });
  };
  return (
    <div className="Tree">
      <div>
        <span>{props.name}</span>
        <button onClick={addChild}>Add child</button>
      </div>
      <div className="children">
        {childState &&
          childState.map((item) => {
            return <TreeNode name={item.name} children={item.children} />;
          })}
      </div>
    </div>
  );
};
const TreeNode = ({ item }) => {
  const addChild = () => {
    item.children = [
      ...(item.children || []),
      { name: `${item.name}-${item.children?.length + 1 || 1}` }
    ];
    update({});
  };
  return (
    <div className="Tree">
      <div>
        <span>{item.name}</span>
        <button onClick={addChild}>Add child</button>
      </div>
      <div className="children">
        {item.children &&
          item.children.map((item) => {
            return <TreeNode item={item} />;
          })}
      </div>
    </div>
  );
};

let update;
const rootElement = document.getElementById("root");
const App = () => {
  [, update] = useState();
  return <TreeNode item={treeData} />;
};
ReactDOM.render(<App />, rootElement);