Home > OS >  How do I recursively render nested components?
How do I recursively render nested components?

Time:05-11

So I'm trying to implement a Comment System with React. (Non-interactive, just to render data). I'm having trouble with how to display the replies of each comment in the view.

comments.js (exports all the comment data)

const comments = [
    {
        ....metadata, // this is where all the metadata for the comment goes, such as the content
        replies: [
            {
                ...metadata,
                replies: [
                    // ...zero or more replies, of the same shape as comments[0]
                ]
            }
        ]
    },
    // ...other comments, of the same shape as comments[0]

export default comments

comment.jsx (the functional component that each element of the comments array above (and the replies of each element) is passed into):

const Comment = props => (
    <div>
        <div>
            {/* this is where all the comment's metadata will be rendered into */}
        </div>

        <div>{props.replies}</div>
    </div>
)

export default comment

App.jsx (what is going to end up being rendered into the DOM)

import comments from "./comments.js"
import Comment from "./comment.jsx"

const App = () => (
    {comments.map(comment => (
        <Comment 
            {...comment.metadata,
            replies:{comment.replies.map(reply => (
                <Comment {...reply.metadata} />
            ))}
            }
        />
    ))
    }
)

The problem with my approach is that replies that are buried more than 1 level deep from the topmost comment (ie replies of replies), won't be rendered into the DOM.

Can anyone please provide a way of rendering all the replies, down to the innermost reply?

Thank you!

CodePudding user response:

please check the following

There is a comment component which loops recursively,

import React, { useState } from 'react';


const Comment = ({ msg }) => {
  return <div>{msg}</div>;
};

export default function App() {
  const [comments] = useState([
    { msg: 'Lorem ipsum 1', replies: [{ msg: 'Lorem 1.1', replies:[{msg: 'Lorem 1.1.1'}] }] },
    { msg: 'Lorem ipsum 2' },
    { msg: 'Lorem ipsum 3', replies: [{ msg: 'Lorem 3.1' }] },
  ]);

  const renderEl = (commentsData) => {
    return (
      <>
        {
          commentsData.map((r, k) => (
            <div style={{ marginLeft: '3%' }} key={k}>
              <Comment msg={r.msg} />
              {r.replies && r.replies.length > 0 ? renderEl(r.replies, 0) : null}
            </div>
          ))
        }
      </>
    );    
  };

  return renderEl(comments);
}

CodePudding user response:

You can use recursion to generate n-level nesting.

const createComment = (comments) => (
  <>
    {comments.map((comment) => (
      <div key={comment.id}>
        <div>{props.text}</div>
        {comment.replies && comment.replies.map(rp => (createComment(rp.replies))}
      </div>
    ))}
  </>
);


export default function App() {
  const comments = [{
    id: 1,
    text: "This is a comment",
    replies: [
      {
        id: 2,
        text: "This is a reply",
        replies: [
          {
            id: 3,
            text: "This is a reply",
            replies: [],
          },
        ],
      },
    ],
  }];

  return (
    <div className="App">
      {createComment(comments)}
    </div>
  )
}
  • Related