Reactjs 中的递归函数

Posted

技术标签:

【中文标题】Reactjs 中的递归函数【英文标题】:Recursive function in Reactjs 【发布时间】:2020-06-21 07:35:08 【问题描述】:

我正在使用递归函数制作动态菜单,并且我已经制作了菜单,并且它以正确的顺序显示,没有任何问题。

我从 service.js 文件中收到菜单数据,您可以在下面的代码沙箱示例中看到整个工作应用程序,

https://codesandbox.io/s/reactstrap-accordion-3uoz9

要求:

这里我需要找出最后一级菜单,并需要将复选框分配为它们各自的 id item.id

例如:

对于第一个菜单一个

 -> [Checkbox with value as 1.1.1] One-One-One
 -> [Checkbox with value as 1.1.2] One - one - two
 -> [Checkbox with value as 1.1.3] One - one - three

对于第二个菜单两个

 -> [Checkbox with value as 2.1] Two - one

.

.

.

对于第六个菜单六个

 -> [Checkbox with value as 6] Six

我希望这一点很清楚,我需要找出递归的最后一层,并应为其分配一个带有其 id 值的复选框。

请fork提供的代码沙箱,帮我实现最后一层checkbox的效果。

可选要求: 如果可能的话,折叠会同时对整个菜单起作用,请使其在每个单独的级别上以唯一的方式折叠。

但主要的重要要求是在菜单的最后一级制作一个复选框。 提前非常感谢...

编辑:

正如 Crowder 所评论的,我已经创建了 sn-p 删除 reactstrap 代码,现在可以了,因为我需要显示复选框内联到子菜单的最新级别(最后一个子元素)。

const menuData = [
  
    id: "1",
    name: "One",
    children: [
      
        id: "1.1",
        name: "One - one",
        children: [
           id: "1.1.1", name: "One - one - one" ,
           id: "1.1.2", name: "One - one - two" ,
           id: "1.1.3", name: "One - one - three" 
        ]
      
    ]
  ,
  
    id: "2",
    name: "Two",
    children: [ id: "2.1", name: "Two - one" ]
  ,
  
    id: "3",
    name: "Three",
    children: [
      
        id: "3.1",
        name: "Three - one",
        children: [
          
            id: "3.1.1",
            name: "Three - one - one",
            children: [
              
                id: "3.1.1.1",
                name: "Three - one - one - one",
                children: [
                   id: "3.1.1.1.1", name: "Three - one - one - one - one" 
                ]
              
            ]
          
        ]
      
    ]
  ,
   id: "4", name: "Four" ,
  
    id: "5",
    name: "Five",
    children: [
       id: "5.1", name: "Five - one" ,
       id: "5.2", name: "Five - two" ,
       id: "5.3", name: "Five - three" ,
       id: "5.4", name: "Five - four" 
    ]
  ,
   id: "6", name: "Six" 
];

class App extends React.Component 
  constructor(props) 
    super(props);


    this.state = 
      currentSelection: "",
      menuItems: [],
      isToggleOpen: false
    ;
  

  componentDidMount() 
    this.setState( menuItems: menuData );
  

  handleClick(id, evt) 
    evt.preventDefault();
    console.log("click handler called with", id);
    this.setState( currentSelection: id );
  

  toggle() 
    console.log(this.state);
    this.setState(
      isToggleOpen: !this.state.isToggleOpen
    );
  

  buildMenu(items) 
    return (
      <ul>
        items &&
          items.map(item => (
            <li key=item.id>
              <div>
                item.name
                item.children && item.children.length > 0
                  ? this.buildMenu(item.children)
                  : null
              </div>
            </li>
          ))
      </ul>
    );
  

  render() 
    return (
      <div>
        <h2>Click any of the below option</h2>
        this.state.menuItems &&
          this.state.menuItems.map((item, index) => 
            return (
              <div key=index>
                item.name
                this.buildMenu(item.children)
              </div>
            );
          )
      </div>
    );
  


ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/4.8.0/reactstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/4.8.0/reactstrap.min.css" />
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.development.js"></script>

【问题讨论】:

@TJCrowder,如果我没记错的话,这就是 react OP 将如何发布问题并提供指向代码沙箱的链接,这是我在 Stack Overflow 中看到的最大内容。即使是有角度的,他们也提供Stackblitz 链接.. 甚至人们只在此类链接中要求最小可复制链接。主要是反应。 我不确定谁投了反对票,尽管我的问题很清楚并且我已经尝试了最大的尝试.. 在哪里你需要得到id?我看不出你打算在哪里使用它。 @TJCrowder,我无法找到在代码 sn-p 中创建两个不同文件的方法,例如 index.jsservice.js,因为它一次只允许一个文件.. 可能我得到你的帮助来做这件事.. @TJCrowder,我已经对我真正需要的东西做了一个简单的sn-p。所以你现在能帮我吗..在我需要分配的最后一个级别之前以相应 id 作为值的复选框.. 【参考方案1】:
buildMenu(items) 
    return (
      <ul>
        items &&
          items.map((item, index) => (
            <li key=item.id>
              <div>
                this.state.isToggleOpen
                (item.children) ?  'Not Last': 'Here you can apply your check box' //this check if item have children 
                <Button onClick=this.toggle.bind(this)> item.name index </Button>

                <Collapse isOpen=this.state.isToggleOpen>
                  item.children && item.children.length > 0
                    ? this.buildMenu(item.children, index)
                    : null
                </Collapse>
              </div>
            </li>
          ))
      </ul>
    );
  

现在渲染的第二种情况

<Button onClick=this.toggle.bind(this)> item.name</Button>

检查项目是否有孩子

(item.children) ? this.buildMenu(item.children) : 'Apply your checkbox here'

完整代码

import React from "react";
import  render  from "react-dom";
import  loadMenu  from "./service";
import  Button, Collapse  from "reactstrap";

// const buildMenu = function buildMenu(items)

// const Menu = ( items ) => buildMenu(items);

class App extends React.Component 
  constructor(props) 
    super(props);
    this.state = 
      currentSelection: "",
      menuItems: [],
      isToggleOpen: false
    ;
  

  componentDidMount() 
    loadMenu().then(items => this.setState( menuItems: items ));
  

  handleClick(id, evt) 
    evt.preventDefault();
    console.log("click handler called with", id);
    this.setState( currentSelection: id );
  

  toggle() 
    console.log(this.state);
    this.setState(
      isToggleOpen: !this.state.isToggleOpen
    );
  

  buildMenu(items) 
    return (
      <ul>
        items &&
          items.map(item => (
            <li key=item.id>
              <div>
                this.state.isToggleOpen
                (item.children) ?  'Not Last': 'Here you can apply your check box'
                <Button onClick=this.toggle.bind(this)> item.name </Button>
                <Collapse isOpen=this.state.isToggleOpen>
                  item.children && item.children.length > 0
                    ? this.buildMenu(item.children)
                    : null
                </Collapse>
              </div>
            </li>
          ))
      </ul>
    );
  

  render() 
    console.log(this.state.menuItems);
    return (
      <div>
        <h2>Click any of the below option</h2>
        this.state.menuItems &&
          this.state.menuItems.map((item, index) => 
            return (
              <div>
                <Button onClick=this.toggle.bind(this)> item.name </Button>
                (item.children) ?  'Not Last': 'Here you can apply your check box'
                <Collapse isOpen=this.state.isToggleOpen>
                  this.buildMenu(item.children)
                </Collapse>
              </div>
            );
          )
      </div>
    );
  


render(<App />, document.getElementById("root"));

【讨论】:

让我知道将我的答案投票为 (item.children) 的原因? 'Not Last': 'Here you can apply your check box' 将检查项目是否还有其他子项,如果没有,则用户可以应用复选框。只是无缘无故地投票不是一种方法。如果有任何问题,我将不胜感激。谁投了反对票。 @TestUser 我没有添加复选框,但您可以使用代码获取最后一个元素。只需将您的 buildMenu 方法替换为上面的方法即可。并添加 (item.children) ? this.buildMenu(item.children) : 'Apply your checkbox here' 在渲染中使用的 它不适用于第一级,例如,foursix.. 我需要为最后一项分配复选框,就像我在左侧给出的问题 [Checkbox with value as 1.1.1] One-One-One 复选框和右侧的相应文本,复选框值为 id 但是不幸的是,您的解决方案不能满足我的需要。无论如何,非常感谢您的帮助和时间..

以上是关于Reactjs 中的递归函数的主要内容,如果未能解决你的问题,请参考以下文章

06python 中的递归函数(python函数)

python中的递归函数

递归函数

Python中的函数递归思想,以及对比迭代和递归解决Fibonacci数列

递归python函数中的持久对象

递归函数中的for循环在递归结束后继续