DEV Community

Elijah Trillionz
Elijah Trillionz

Posted on • Updated on

Shouldn't recursion be prevented in React component?

I had an error recently while working with React/Next.js and styled-components. I was to create a styled component for one of my app's regular components but accidentally gave it the same name.

This lead to an infinite loop in the browser. This is the first time I have experienced such error in React, and my problem was that there was no hint whatsoever as to what is wrong.

ESLint in webstorm wouldn't call it an error, because recursion do exists and it's not an error.

So I was thinking, is there no way React or should I say Next.js could have failed while compiling.

I know recursion can exist and isn't and shouldn't be logged as an error, but then should recursion exist in React?
How does calling a component inside of that component do something useful? I don't know if you guys do anything like that? Please share what you do with it.

My point is, if there is really no point of having a component inside of itself, then why not throw an error if that happens!

Top comments (6)

Collapse
 
elfsternberg profile image
Eλf Sternberg

I have a form manager for a very complex use case: insurance forms. Now, forms consist of questions ("Do you have a house or a mobile home?") that can trigger the addition of nested questions ("Does your house have a swimming pool?") that can trigger even MORE nested questions ("Does your swimming pool have a gate?") which can lead to MORE nested questions ("Can the gate be locked?").

We want to ONLY show the questions that are relevant. The worst thing about filling out a complicated bureaucratic document is figuring out if a question is relevant to you at all. That section on "Does your roof have B-Clips rated for 8 pound missiles traveling no faster than 40MPH?" applies only to mobile homes in Florida USA, for example. (By "missile" they mean "rock" and by "40MPH" they mean "in a hurricane"). So this is a TREE of questions. And we want the customer to never see questions that aren't important.

You have raw text input, drop downs, radio buttons, checkboxes, and to be super-fancy some of your radio buttons can have icons-- which have one layout-- or photographs-- which have a different layout. Your root question collections have one presentation, and your nested question collections (That "Does your swimming pool have a latch?" has a lot of sibling questions about elevation, screened-in areas, covers, etc.) have a different presentation.

How do you manage this? With recursion!

You use a dispatch function that takes the tree of question collections and renders them: where it encounters a question, it first asks "Does the data the custom has input so far justify rendering this thing?" If the answer is Yes, it draws the appropriate Input component.

Where it encounters a nested collection, it dispatches to the rendering function for the nested collection, which in turn recursively calls the dispatch function for each of ITS children, and if any of those children are further nested, the dispatch function calls the nested handler, which in turn calls the dispatch function... until all the leaves of the tree have been rendered.

HTML is a tree. The DOM is a tree-- and each node has an ordered node of children, exactly like the collection of questions in a deep and dynamic form. Lots of data is trees. The way you turn a tree of data into a DOM tree when you don't know how deep the source data tree will be is with recursion-- the core handler Component recurses to ITSELF when one of its child objects to render is a node, and calls the appropriate Component when it's time to render the terminal leaves.

Recursion is the fine art of taking a large and complex collection of problems, popping off one problem and solving it, putting the answer into a container, and then calling yourself on the now-smaller collection of problems. (You can get away with a for loop if it's just an array... but for anything else, you're gonna need recursion!) The problem here is "I have a tree of unknown size... how do I render it?" Unless you want to put a LOT of effort into building a collection of functions-at-depth to cover every possibility, the answer is recursion.

To prevent recursion in React is to prevent React from working. The reconciler at its heart processes a tree to decide out what needs re-rendering, and it uses recursion to descend through that tree and collect its decisions.

Collapse
 
elijahtrillionz profile image
Elijah Trillionz

Totally get this use-case, I have actually made something similar in devRoadMap.vercel.app..

But I just didn't think it would be useful having a recursive component, but now that I think of these components as more of HTML elements in the DOM, I can now see how useful it is.

To prevent recursion in React is to prevent React from working. The reconciler at its heart processes a tree to decide out what needs re-rendering, and it uses recursion to descend through that tree and collect its decisions.

Yeah this is true. My question wasn't really if recursion should be removed from React, because we can't really get it out, I was actually concerned about recursion that I had to do with components within the app.

Thanks a lot for sharing, I can now see things differently

Collapse
 
kallmanation profile image
Nathan Kallman

A classic example for recursive components is nested comments: medium.com/@singhajendra1998/recur...

I'm sure there are many others

Collapse
 
elijahtrillionz profile image
Elijah Trillionz

Oh wow, that's a really good use-case. I don't think I would have done it that way though. Thanks for sharing.

Collapse
 
henripodolski profile image
Henri Podolski • Edited

See an example here: youtu.be/L-gfTMpIag8 recursively walking and rendering a file and folder tree in a React live coding session. Recursion is the best pattern, when you do not know how many levels of the same thing to expect

Collapse
 
yogeshdatir profile image
Yogesh Datir

This tree component shares a little better way to handle recursive components. The recursion can be taken care in JS array of nested objects with an utility function that flattens the array of nested objects into a flat one and then renders it. Hierarchy is visualised using conditional styling.