Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
November 18, 2022 07:08 pm GMT

Recursive rendering in React

In one of my very first tech interviews earlier this year, I was given an interesting problem and I terribly messed it up. Meaning I couldnt solve it. And the solution to the problem was recursion but in react. So I decided to write a blog about it.

What is Recursion?

In computer science, recursion isa method of solving a computational problem where the solution depends on solutions to more minor instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code.

For example, a factorial(5) is 5*4*3*2*1. If we want to solve it recursively, we can say a factorial(5) is 5 times the factorial(4): 5*4!

And factorial(4) is 4*3! until we reach the number 1.

5!    5 * 4!        5 * 4 * 3!            5 * 4 * 3 * 2!                5 * 4 * 3 * 2 * 1

We eventually reach the same solution which is 5 * 4 * 3 * 2 * 1. If we have to write a function for factorial we can write the following:

function factorial(n){   return n * factorial(n  1);}

If we invoke the factorial() function and pass an integer n, it will keep calling the factorial() * n, and in each invocation, n will be n-1.

Image description

However, we have a serious problem. We did not tell our function when to stop and therefore our factorial() function will end up in an infinite loop and we will never reach the solution. Telling the function when to terminate is called a base case. Base case is always required when defining a recursive function. The base case in this case would be n = 1. Since factorials of numbers that are less than 1 don't make any sense, we stop at the number 1 and return the factorial of 1 (which is 1).

function factorial(n){    if(n === 1)        return 1;    else        return n * factorial(n  1);}

Now if we pass 5 as n: factorial(5)

Image description

How do we handle recursion in React?

What would a recursive call look like in react? Lets say you are making an API call and the response data has children that is also the same key and value format.

{  text: "some text",  data: {      text: "some text",      data: {        text: "some text",        data: {          text: "No more data here"        }    }  }}

As you can see the object data is continuously stacked on top of another data object. We can have indefinite amount of stacked data. Using recursion we will render the data.

Say that our component is called <RecursivelyRenderComponent> which takes the data object as a prop and will render the text inside the data object.

function RecursivelyRenderComponent({ data }) {  return (    <div>      <h1>{data.text}</h1>    </div>  );}

This will return the first instance of the text. But what about the nested ones?

We need to recursively return the same component within itself for the amount of time we encounter data.

Our recursion will look like:

  • Base case: If data doest exist we stop recursion
  • Recursion rule: If data exist render <RecursivelyRenderComponent> again and pass data as a prop.

Our component will look like this:

function RecursivelyRenderComponent({ data }) {  if (data.data)    return (      <div>        <h1>{data.text}</h1>        <RecursivelyRenderComponent          data={data.data}        ></RecursivelyRenderComponent> {/*calling the same component recursivly */}      </div>    );  else return <h1>{data.text}</h1>;}

We can simplify it more using ternary:

function RecursivelyRenderComponent({ data }) {  return (    <div>      <h1>{data.text}</h1>      {data.data ? (        <RecursivelyRenderComponent          data={data.data}        ></RecursivelyRenderComponent> {/*calling the same component recursivly */}      ) : null}    </div>  );}

And our DOM will look like this:

Image description

Lets analyze a real-life scenario

Image description

This is a thread from a random Reddit post. As seen in the picture a Reddit post can have multiple replies, and the replies can also have multiple replies. The replies to a post can be heavily nested. In this example, each new thread has a space and a line indicating the parent reply. Similar to our previous example of <RecursivelyRenderComponent/>, this type of data could be handled using recursion.

How do we render reddit style replies?

Sample response data:

const data = [  {    post: {      id: 1,      author: "goodKitty",      title: "A day in a life of a kitten!",      text: "Claws in your leg the best thing in the universe is a cardboard box lie on your belly and purr when you are asleep so chase ball of string yet i like big cats and i can not lie wake up human for food at 4am. Ask for petting stand with legs in litter box, but poop outside yet climb leg, yet favor packaging over toy. Stare at wall turn and meow stare at wall some more meow again continue staring the dog smells bad miaow then turn around and show you my bum and cry louder at reflection yet missing until dinner time lasers are tiny mice.",      reply: [        {          author: "KittyLord",          text: "Love it!",          reply: [            {              author: "Hungrycat22",              text: "Meow To!",              reply: [                {                  author: "catnipDealer",                  text: "purrrrrrrr!!",                  reply: [                    {                      author: "KittyLord",                      text: "Purrfect!",                    },                  ],                },              ],            },            {              author: "Hungrycat22",              text: "Mice!!!",            },          ],        },        {          author: "CatM0m",          text: "I have a cat!",          reply: [            {              author: "dirtyKitten",              text: "I have 2 cats",              reply: [                {                  author: "CatM0m",                  text: "Hahahaha",                },              ],            },          ],        },      ],    },  },]

This is similar data to a Reddit post. We have posts, which contains replies, and the replies contain more replies. The replies should be rendered under the post and should keep nesting under other replies until there are no replies in the data.

function Reply({ reply }) {  return (    <div>        {reply.author} replied      </p>        {reply.text}      </p>      <div>         {reply.reply           ? reply.reply.map((reply) => <Reply reply={reply}></Reply>)           : null}      </div>    </div>  );}

Our <Reply/> component takes a prop reply, it renders the author and text of the reply and check if the data has any reply inside. If there is a reply field, we map through it (since reply returns an array) and re-render the <Reply/> for each element of the array and pass the element as a prop: reply.reply.map((reply) => <Reply reply={reply}></Reply>).

If there is no reply we stop the recursion and thats our base case.

Adding some forum style spacing to it.

function Reply({ reply }) {  return (    <div>      <p        style={{          marginLeft: "10px",          textDecoration: "underline",          color: "grey",          fontStyle: "italic",        }}      >         {reply.author} replied      </p>      <p        style={{          marginLeft: "10px",                  backgroundColor: "beige",          padding: '20px'        }}      >        {reply.text}      </p>      <div className="forum">        <div className="break"></div>        <div>          {reply.reply            ? reply.reply.map((reply) => <Reply reply={reply}></Reply>)            : null}        </div>      </div>    </div>  );}

Css:

.forum{  display: flex;  flex-direction: row;}.break{  /* this is the line */             margin-left: 40px;  background-color: cadetblue;  width: 2px;}

Lets also render the post data in our <App/> component and render the replies.

function App() {  return (    <div className="App">      <h1>{data[0].post.title}</h1>      <p>By: {data[0].post.author}</p>      <p>{data[0].post.text}</p>      {data[0].post.reply        ? data[0].post.reply.map((reply) => <Reply reply={reply}></Reply>)        : null} {/* we are mapping through the direct replies to the post */}    </div>  );}

And finally our DOM will look like:

Image description

Its as simple as that. This will work for indefinite amount of nested data without a problem.


Original Link: https://dev.to/mohhossain/recursive-rendering-in-react-24b

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To