React Component - Yours Recursively!

React Component - Yours Recursively!

ยท

5 min read

Ever Wondered why Recursion would ever be needed in Front-End?

Well it turns out, it's needed!

To give you a real-life example, did you ever observe how the comments for any Social Media post has reply feature to it.

Additionally, even replies have replies! Now if you notice the component or the individual comment is the same design no matter how deeply nested it is.

Yep! You guessed it right. That's where recursion is achieved in front-end from the data that you receive.

My aim with this blog is to make you understand Recursion in as simple terms and less code as possible with respect to <React/>.

The example I am taking here is the same comment-reply inception going on around social media posts.

Here's a sneak peak into what you'll be going to make after finishing this blog. Check it out so you know what you are going to build

Now that its clear what is it all about, let's do it....!!

"Talk is cheap, show me the code" - Linus Torvalds

1. Create an Empty React Project.

Note: As this is not a CSS specific tutorial, you can directly take the corresponding stylesheet used in this project from this repo. And this is not the best UI/UX out there. So watch out xD!


2. Make a json data which comprises of a single post information.

Here's a sample json which I created inside my react project's src folder.

export const postInfo = {
  post: {
    author: "Farhan Qureshi",
    postImage:
      "https://4.img-dpreview.com/files/p/E~TS590x0~articles/3925134721/0266554465.jpeg",
    postDescription: "A bird chirping on the stem of a plant"
  },
  comments: [
    {
      userName: "KRK",
      comment: "Ye picture hai?",
      likes: 0,
      replies: []
    },
    {
      userName: "Elon",
      comment: "Should I Buy It ???",

      likes: 420,
      replies: [
        {
          userName: "Parrot",
          comment: "Dude! Get Some Help!!",
          likes: 10,
          replies: [
            {
              userName: "Elon",
              comment: "That's it! Get into the Cage!",
              likes: 300,
              replies: []
            }
          ]
        },
        {
          userName: "Jeff Bezos",
          comment: "Are you insane, Elon?",
          likes: 0,
          replies: []
        }
      ]
    },
    {
      userName: "Farhan Qureshi",
      comment: "Bhai! Ye kya ladai ho raha hai mere photo pe",
      likes: 100,
      replies: [
        {
          userName: "Rancho",
          comment: "Jaake tere abbu ko dikha. Khush ho jayega",
          likes: 100,
          replies: []
        },
        {
          userName: "Raju",
          comment: "Farhan. Photoshoot ko jaana hai camera leke aa",
          likes: 20,
          replies: [
            {
              userName: "Farhan Qureshi",
              comment: "Saala sudhartha nahi thu!",
              likes: 5,
              replies: []
            }
          ]
        }
      ]
    }
  ]
};

Tell me you already got that this post is going to be hilarious ๐Ÿ˜…

The array of comments is all we care about mostly.


3. Bring this to the App.js

De-structure out the required properties from the object.

Your Post goes like this :

import { postInfo } from "./postInfo";
import "./styles.css";

export default function App() {
  const {
    post: { author, postImage, postDescription },
    comments
  } = postInfo;
  return (
    <div className="Post">
      <section className="author-info">
        <img
          src={`https://via.placeholder.com/50/7b1112?text=${
            author.split("")[0]
          }`}
          alt={author}
        />
        <h3>{author}</h3>
      </section>
      <img className="post-img" src={postImage} alt={postDescription} />
    </div>
  );
}

So far the UI looks like this

image.png

Time for the exciting part.


4. Make <Comment/> component.

Make a component at /src/components/Comment/Comment.js

import "./Comment.css"

export const Comment = ({ currComment, author }) => {
  const { userName, comment, replies, likes } = currComment;

  return (
    <div className="comment">
      <img
        src={`https://via.placeholder.com/50/7b1112?text=${
          userName.split("")[0]
        }`}
        alt="user-profile-pic"
        className="user-img"
      />
      <section className="user-info">
        <h3>{`${userName} ${
          author && author === userName ? "(Author)" : ""
        }`}</h3>
        <p>{comment}</p>
        <small>{`Replies - ${replies.length}`}</small>
      </section>
      <span>{likes} &hearts;</span>
    </div>
  );
};
  1. currComment prop : The exact comment which you want to show
    • userName : User who posted the comment
    • comment : The actual comment the user has written
    • likes : Number of likes to the comment
    • replies : The replies on the current comment ( Here's where we traverse recursively as each reply is in the similar format of an actual comment).
  2. author prop : Author of the post which we take from the post information. (Optional Feature just to distinguish the author of the post from the comments section if the author has commented or replied on his posts.

** Use this component in App.js

Import the Comment component and use it in App.js this way.

<h3>{`Comments - ${comments.length}`}</h3>
      {comments.map((comment, id) => (
        <div className="comment-container">
          <span>{id + 1}</span>
          <Comment key={id} currComment={comment} author={author} />
        </div>
      ))}

Let's do a quick UI check :

image.png

Woaah!!! We're half way there.

Yes. It's just half-way. Now comes the hard part to recursively render the replies of comment. Or say, replies of replies of comments.


5. Handle Replies to each comment.

Points to note :

  1. Check whether there are replies present to an individual comment
  2. Make a state variable to hide/show the replies to a comment.

Now let's make few changes in Comment component

 const commentHasReplies = replies.length > 0;

  const [showReplies, setShowReplies] = useState(false);

  return (
    <div className="comment-wrapper">
      <div className="comment">
        <img
          src={`https://via.placeholder.com/50/7b1112?text=${
            userName.split("")[0]
          }`}
          alt="user-profile-pic"
          className="user-img"
        />
        <section className="user-info">
          <h3>{`${userName} ${
            author && author === userName ? "(Author)" : ""
          }`}</h3>
          <p>{comment}</p>
          <small>{`Replies - ${replies.length}`}</small>
        </section>
        <span>{likes} &hearts;</span>
      </div>
      {commentHasReplies && (
        <p
          className="fake-link"
          onClick={() => {
            setShowReplies((state) => !state);
          }}
        >
          {showReplies ? "Hide Replies..." : "Show Replies..."}
        </p>
      )}
      {showReplies
        ? replies.map((reply, id) => (
            <div className="reply" key={id}>
              <Comment currComment={reply} author={author} />
            </div>
          ))
        : ""}
    </div>
  );

Look at how we used Comment component inside Component to render the replies. That there is called recursion.

As soon as we reach the point where there are no replies, it comes out of the recursive call and map an actual reply to the post and similarly this goes on and on till the comments end.


This is what you have made.

react recursion.gif

If you reached till this part, I request you to leave a comment about how you felt or how good was your understanding from this blog, also the areas I could improve explaining things even better. ๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€

Stay tuned for more awesome blogs ๐Ÿš€๐Ÿš€๐Ÿš€.

ย