Create more extensible React components with the “as” prop pattern

Eric Masiello
Level Up Coding
Published in
3 min readMar 16, 2020

--

Colorful pattern

React components bake HTML semantics into their implementation. Take this Title component example:

While this isn’t a particularly interesting or robust component, it will help illustrate a useful concept. This component creates an HTML h1 element, applies a className prop set to "title" to style it, and then allows the consumer of the component to pass along whatever content they’d like to render using the children prop. In this case, the semantics is the heading level 1 expressed as an h1 element.

The component can then be used like so:

We can expect the Demo to yield something to the effect of:

Based on this, we can clearly see the Demo creates a section element and the Title an h1. For this simple, albeit contrived use case, this works fine.

What do we do when we need our Title component to render something else? We might need it to render as an h2 or perhaps a plain div. We often want this flexibility when optimizing for SEO or to improve the accessibility of a page (conveniently improving one of these often improves the other). Whatever our reason, how do we handle this? Creating a TitleH2 or a TitleDiv that does nothing more than swap out the wrapper HTML element with a different one seems far from D.R.Y. As you have likely guessed by now, this is where the as prop can be utilized to great effect.

The as prop

Here’s what using the as prop looks like:

The as prop is instructing the component (Title) to render its wrapper element as something else. If we don’t specify an as prop, the component will use a default value it has defined internally.

Here’s how it works in code:

Let’s break down what’s happening here. Within the Title function, we’re destructuring two properties off of props: as and children. Nothing has really changed with the use of children from the original code other than we’re now using the destructured variable in place of props.children. The as prop we’ve also destructured and then aliased to a new constant called Component. Thanks to defaultProps, if the consumer of Title does not specify a value for as, Component will evaluate to 'h1'. In that case, Title will render:

However, if the user of Title does specify an asvalue, then that becomes what is rendered.

Why alias the as prop to Component?

Similar to the name “as”, the name Component is somewhat arbitrary. The important part is that when you return the prop in the context of a React element (e.g. <Component />) it must be capitalized. That’s just a rule of React. Lowercase component names are reserved for DOM nodes and come from the react-dom library.

Using as with custom components

A cool thing about the as prop is that it isn’t limited to HTML elements. You can pass in custom React components without any additional work. Let’s pretend we have a component called SpecialButton that we wanted to style to appear like a Title but render as a button.

If we breakdown what this is doing, it looks like this:

Note that in order for the Title component styles (i.e. className="title") to properly forward to the final <button />, we need to destructure the className on the SpecialButton component and then forward the prop along to the final button.

As was the case in SpecialButton, I find forwarding along the className prop to be a useful general best practice. I plan to expand upon this in a follow-up post where I will illustrate a more robust way of handling className and other props you may want to forward along.

So that’s how it all works. There’s nothing special about the as prop. It's just a prop like any other.

--

--