Recursion using ReactJS Components

Recursion is a powerful tool in any programming language, tool or framework. However, very rarely do we see good usage of recursion in code, especially in those using ReactJS.


Motivation for using recursion

Why you might consider using recursive components in your code :

  1. Recursion minimizes code to a great extent.
  2. Code modules become highly readable and easy to understand.
  3. Encourages the developer to find the “invariant” (more on this later). Finding this invariant, can reduce seemingly complex problems into extremely simple ones.
  4. Code gets easy to manage, maintain and extend since the code is highly structured.

Can your problem be reduced using recursion?

A question that you need to ask yourself if you want to solve a problem using recursion is “Can I reduce this problem into a structure that keeps on repeating itself over and over again?
This is the fundamental idea behind recursion. This is known as the invariant of the problem or something that can be generalized and is repeated.


Transforming a problem into a recursive one

Three main constructs are required in order to use recursion on a problem.

  1. The seeder
  2. The invariant
  3. The base case

Example

Let’s consider a very simple example: rendering a triangle pattern using a React component, like the one shown below.

The input to the component, taken as props, would be the height of the triangle, in this case 5.


Code

Let the driver component render the following,

var Driver = React.createClass({
render: function() {
return(
<div>
<Triangle n={5}/>
</div>
)
}
});

This is the “Seeder”. The recursive Triangle component gets an initial seed of 5. The component is abstracted out and expected to print the triangle only with this information.

Let’s define the Triangle component as follows :

var Triangle = React.createClass({
render: function() {
var n = this.props.n;
if(n == 1)
return (printable(n))
return(recurse(n));
}
});

The n == 1 condition is the “Base Case”. This informs the component when to stop recursing or else the browser would reach the call stack limit.

var printable = function(n) {
var results = ""
for(var i = 1;i<=n;i++) {
results += "*"
}
return(<div>{results}</div>)
}
var recurse = function(n) {
return(
<div>
{printable(n)}
<Triangle n = {n-1}/>
</div>
)
}

printable() is just a simple method that renders a div with a given number of * patterns based on the input.

Nowrecurse() is really the brains behind the execution here. recurse() is used as a separate method to enable Triangle to call itself. At each call, recurse() would call Triangle with the modified value of n=n-1 , rendering div after div.
The recursion ends when recurse() sends a value of 1 to Triangle .recurse() is the “Invariant” in this case. It enables generalizing of the problem.


Where can you use recursion?

Recursion can be used anywhere , where you have found the invariant. These fall into “Tree” type problems, where the rendering flow and logic resembles a tree. Simple examples could be where a pattern of divs have to be rendered such as the example mentioned above.
More complex examples would be those having computational logic involving states or redux stores. An example would be, rendering a tree directory structure such as this :

It would require state changes based on clicks on each row keeping other fields such as the right most ones constant. The code can get really elegant using recursion once the invariant has been found.