我正在try 解决一个JavaScript/React.js练习来练习递归函数,在该练习中,您有一个输入对象(可以有多个深度级别),并且您希望输出一个包含如下对象内容的"树":

//Input object
const input = {
  key1: {
    key11: 'v11',
  },    
  key2: {
    key21: {
      key211: 'v211',
    },
  },
  key3: 'v3',
}

/* Desired output:
key1:
--key11: v11
key2:
--key21:
----key211: v211
key3: v3
*/

我已经成功地开发了进行递归调用的App.jsx组件:

class App extends React.Component {  
    renderObject(input, level=0){
    return (Object.entries(input).map((item, index) => {
      if(typeof item[1] === "string"){
        let object = <div key={`${item[0]}-level-${level}`}><span>{"--".repeat(level)}</span>{item[0]}: {item[1]}</div>;
        level = 0;
        return object;
      } else {
        let object = <div key={`${item[0]}-level-${level}`}><span>{"--".repeat(level)}</span>{item[0]}: { this.renderObject(item[1], ++level)}</div>
        return (object)
      }
    }))
  }
  
  render() {
    return (
      <div>
            {this.renderObject(input)}
      </div>
    )
  }
}

ReactDOM.render(<App />, document.querySelector("#app"))

我面临的问题是,我实现的level没有显示出真正的深度,因为它也在第一个级别的每次迭代中递增(当它应该保持为0的时候).

/* Obtained output: 
key1:
--key11: v11
--key2:
----key21:
------key211: v211
----key3: v3
*/

我怎么能解决这个问题呢?

推荐答案

将我的注释转换为答案,这个问题与在递归函数体中使用++levellevel = 0来改变值level有关.查看打印的结果,目标是每个级别具有相同的缩进,因此对于++level,循环中同一级别的future 同级将以越来越大的距离缩进.level = 0可能试图纠正这个问题,但它不起作用,因为一旦开始递归,Level就不应该为0.

解决方案是在函数体期间将level视为有效不可变的,然后使用level + 1作为参数将子递归调用设置为适当的级别.

代码如下:

class App extends React.Component {
  renderObject(o, level = 0) {
    return Object.entries(o).map(([k, v]) => (
      <div key={[k, v, level].join("-")}>
        <span>{"--".repeat(level)}</span>
        {k}:{" "}
        {typeof v === "object"
          ? this.renderObject(v, level + 1)
          : v}
      </div>
    ));
  }

  render() {
    return <div>{this.renderObject(this.props.tree)}</div>;
  }
}

const tree = {
  key1: {
    key11: "v11",
  },
  key2: {
    key21: {
      key211: "v211",
    },
  },
  key3: "v3",
};
ReactDOM.render(
  <App tree={tree} />,
  document.querySelector("#app")
);
#app {
  font-family: monospace;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Javascript相关问答推荐

Next.js Next/Image图像隐含性有任何类型-如何修复?

使用JavaScript单击上一个或下一个特定按钮创建卡滑动器以滑动单个卡

防止用户在selectizeInput中取消 Select 选项

使用i18next在React中不重新加载翻译动态数据的问题

在nextjs服务器端api调用中传递认证凭证

使用GraphQL查询Uniswap的ETH价格

变量的值在Reaction组件中的Try-Catch语句之外丢失

使用Java脚本导入gltf场景并创建边界框

当使用';字母而不是与';var#39;一起使用时,访问窗口为什么返回未定义的?

更新动态数据中对象或数组中的所有值字符串

使用带有HostBinding的Angular 信号来更新样式?

TinyMCE 6导致Data:Image对象通过提供的脚本过度上载

如果没有页面重新加载Angular ,innerHTML属性绑定不会更新

将嵌套数组的元素乘以其深度,输出一个和

将多个文本框中的输出合并到一个文本框中

无法设置RazorPay订阅API项目价格

我正在试着做一个TicTacToe Ai来和我玩.但是,我试着在第一个方块被点击时出现一个X,然后在第二个方块之后出现一个O

如何正确地在ComponentWillUnmount中卸载状态以避免内存泄漏?

使用jQuery每隔几秒钟突出显示列表中的不同单词

如何使用Angular JS双击按钮