Building Robust Components with React Children
A Quick Introduction to React Children
At Hootsuite we use a global front-end component library that we share across applications to create a cohesive and intuitive user experience. This practice often requires creating versatile components. While some components will naturally have a relatively narrow scope, others might be useful across a variety of different products. One way to build components that mitigate tight coupling is to make use of React’s built-in children prop. Building components using React children is a great way to write structured yet reusable components. It allows us to have a large degree of control over components while preserving flexibility and safely handling arbitrary props.
Let’s take a simple navigation drawer as an example:
Imagine we want to share the same styles and animations between all our navigation drawers, creating a predictable and comfortable user experience across all of our apps. Although we may want all these drawers to have identical styling and animations, we might need our menu items to differ depending on context. Maybe we need a drawer with links only in one app, and in another we want some menu items that act as accordions — buttons that open a secondary list of submenu items. In order to make the drawer robust enough to handle these potential differences, we can use
React children can be passed down to a component by nesting them inside the component’s root JSX tag. We can then access them in that component using
props.children. Here is what our navigation drawer component might look like if we are passing it some menu items:
Our NavDrawer component handles children by rendering them in an expression container:
Which outputs the following in HTML:
React children utilities
What if we want a little more uniformity in our menu items, like giving each menu item some specific styling by wrapping each one in a styled component? For brevity’s sake, let’s say we want to wrap each menu item in a div to give each menu item a bottom border, regardless of what that menu item may be:
We can use
React.Children.map to accomplish this!
React.Children’s map utility is especially useful because it returns
null if children is either
undefined, and it also automagically adds a key to each rendered child! Here’s what
React.Children.map looks like in action:
Our NavDrawer now looks like this under the hood in HTML:
Using Slots to Designate Structure
What if we decide we want to enforce just a bit more structure and split up our NavDrawer component, separating its contents? We can actually pass JSX as a prop, then designate these elements to be rendered in specific “slots” in the component they are passed into. Let’s say we want to divide our NavDrawer into two sections: a “title” slot at the top, and anything else below it. We can do this by having NavDrawer accept a “title” prop:
Note that the prop we are passing is named “title”. We can actually pass children as props without using the standard “children” prop name.
Next, let’s pass our title prop to NavDrawer, where NavDrawer handles and styles it as necessary (I’m placing it in an
<h2> for simplicity):
Keep in mind the above code is a simplified example. There are more
React.Children utilities available for use, such as
Using React children props can help you construct flexible, robust components that are useful in a variety of different scenarios while adhering to the DRY principle. Don’t be afraid to dive in and take advantage of this built-in React feature in your next project!
Jenn MacFarlane is taking her second degree, a Bachelor’s of Computer Science (BCS) at the University of British Columbia (2019). She spent 4 months at Hootsuite (May-August 2018), where she joined the WebDev team.
Connect with me on Linkedin!