Using the Children Prop for DRY UI Components

At work this week, I was given a new set of wireframes that built on some screens I already made. These screens used a single React Native FlatList component to render three different sets of data on different pages. The new wireframes required two of these lists to display slightly different data, while the third stayed identical to the component I already made. I ended up making a component that rendered the base list item and used the children prop to display the different content.

I used to think that the children prop was something serious that Higher Order Components used to pass down utilities like context. It wasn’t until I needed such a solution that I realized it could be used to avoid duplicating code in simple UI situations.

To illustrate this, I created a similar example with React. This example uses a restaurant menu with two lists: food and beverage. These food and beverage items have some shared content, such as title, price, and allergy information. They also have content that is unique to their type: food items have a list of ingredients, and beverage items display the origin and ABV percentage.

The index.js file renders the list component with two different sets of data. This data is mapped through, and the list item is conditionally rendered.

function Lists({list, type}){return (  <section>    <h2>{type}</h2>     {list.map(item => type == 'Food' 
? <ListItemFood {...item} key={item.id} />
: <ListItemBeverage {...item} key={item.id}/>)}
</section>)}

ListItemFood and ListItemBeverage work similarly. They take in the item and pass the appropriate props to the HOC ListItem, which does most of the heavy lifting. The type-specific item components also render type-specific data. Here, ListItemFood is rendering the list of the ingredients.

function ListItemFood({ingredients, name, price, restrictions}){return (  <ListItem name={name} price={price} restrictions={restrictions}>    <ul>      {ingredients.map((i, index) => <li key={index}>{i}</li>)}    </ul>  </ListItem>)}

The JSX that is wrapped with the ListItem component is rendered inside that component with the children prop, in addition to the name, price, and dietary information, which is displayed both for food and beverages.

function ListItem({children, name, price, restrictions}){return (  <div>    <div>      <h3>{name}</h3>      <span>{price}</span>      {restrictions && <div>
{restrictions.map((r, index) =>
useDietaryRestrictionsIcon(r, index))}
</div>}
</div> {children} </div>)}

Software Engineer specializing in React Native but passionate about the future of tech beyond mobile