I am trying to solve a JavaScript/React.js exercice to practice recursive functions in which you have an input object (that can have multiple depth levels) and you want to output a "tree" with the object content like below:
//Input object
const input = {
key1: {
key11: 'v11',
},
key2: {
key21: {
key211: 'v211',
},
},
key3: 'v3',
}
/* Desired output:
key1:
--key11: v11
key2:
--key21:
----key211: v211
key3: v3
*/
I have managed to develop the App.jsx component that makes the recursive calls:
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"))
The problem I am facing is that the level
I have implemented is not showing the real depth, because it also increments in each iteration in the first level (when it should remain 0).
/* Obtained output:
key1:
--key11: v11
--key2:
----key21:
------key211: v211
----key3: v3
*/
How could I solve this?
CodePudding user response:
Converting my comment to an answer, the problem is related to mutating the value of level
with level
and level = 0
in the body of the recursive function. Looking at the printed result, the goal is for each level to have the same indentation, so with level
, future siblings in the loop at the same level will be indented at increasing distances. level = 0
might have been an attempt at rectifiying this problem, but it doesn't work because level shouldn't be 0 once the recursion starts.
The solution is to treat level
as effectively immutable during the body of the function, then use level 1
as the parameter to set up the child recursive calls to the appropriate level.
Here's the code:
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>
CodePudding user response:
Do level 1
instead of level