Recursive React components
- React.js
- TypeScript
React functional components can be used recursively, and this should not be surprising at all (they are functions, after all), yet for some reason it's not something easy to catch at first glance. Let's see a basic example.
Use case
Let's consider the following array of nested objects representing the departments structure of a company:
export default [ { id: '1', department: 'Sales', subdepartments: [ { id: '1-1', department: 'Research', }, { id: '1-2', department: 'Customer relationships', }, ], }, { id: '2', department: 'IT', subdepartments: [ { id: '2-1', department: 'Development', subdepartments: [ { id: '2-1-1', department: 'Web development', }, { id: '2-1-2', department: 'Applications development', }, ], }, { id: '2-2', department: 'Solutions', }, { id: '2-3', department: 'Technical support', }, ], }, { id: '3', department: 'Human resources', }, ]
As you can see, each department and subdepartment can have "n" number of subdepartments. This would be a good use case for a recursive solution because we don't know how many subdepartments are contained within a single department or subdepartment.
As with any recursive function, the most important thing to consider is the base case, which is the condition that will basically tell the function to stop calling itself.
Recursive functional component
With all that being said, let's see how we could write this recursive component:
import departments from './company' interface Department { id: string department: string subdepartments: Department[] } interface Props { departments: Department[] } const Departments = ({ departments }: Props) => ( <ul> {departments.map(({ id, department, subdepartments }) => ( <li key={id}> <h3>{department}</h3> {subdepartments !== undefined && ( <Departments departments={subdepartments} /> )} </li> ))} </ul> )
The base case here is quite simple: if the subdepartments property is undefined, then stop the execution.
That's all for this article, hope you found it interesting. See you in the next one!