Honey, I Type Checked The Children

Laurie - May 13 '19 - - Dev Community

Join me as we continue on our quest to explain and understand boilerplate code!

Today we're going to dive into PropTypes in React. I was actually prompted to do this because of some template code that shows up when you use the gatsby new <project-name> command.

The first thing that jumped out at me was a code snippet that appears in layout.js.

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}
Enter fullscreen mode Exit fullscreen mode

What's interesting about this line of code is that it isn't technically Gatsby that is in charge here. This is actually React code (Gatsby is built on React), but it's included out of the box for Gatsby cli starter projects.

Catch your bugs!

Proptypes is a feature in React that helps validate the values being passed through props.

If you aren't familiar with props there is a bit of an overview in this post.


The idea is that PropTypes can catch mismatches in the type of data being passed from one component to another. For example, if msg is a String, but the component it's passed into is expecting a number. Even without Typescript or other type supported JavaScript extensions, React provides PropTypes as a built-in typechecking ability.

PropTypes in Action

PropTypes works at two levels. It ensures that the right type of data is passed into a particular component. It also checks to make sure a component is receiving the correct data type.

This post might help you understand components as a concept.

In the case of the code we started with, it is setting PropTypes for the Layout component. That is, defining validation for the props passed into Layout.

Layout.propTypes = {
     ...stuff goes here...
}
Enter fullscreen mode Exit fullscreen mode

Where did the children come from?!

This is the Layout component the starter project comes with. Take a look at the props being passed into this component. It's passing a prop called children and referencing it in the body of the render function.

const Layout = ({ children }) => (
    render={data => (
      <>
        <Header siteTitle={data.site.siteMetadata.title} />
          <main>{children}</main>
          <footer/>
        </div>
      </>
    )}
)
Enter fullscreen mode Exit fullscreen mode

Now let's look at an example of how the Layout component itself is used. We can find such an example in the NotFoundPage component generated by the starter project.

const NotFoundPage = () => (
  <Layout>
    <SEO title="404: Not found" />
    <h1>NOT FOUND</h1>
    <p>You just hit a route that doesn&#39;t exist... the sadness.</p>
  </Layout>
)
Enter fullscreen mode Exit fullscreen mode

Well, that's kind of weird. At first glance Layout doesn't appear to be using props at all. Typically, props are passed as a key-value pair that appears in the open tag of a component. Something like this.

<Example msg="test" />
Enter fullscreen mode Exit fullscreen mode

Then inside the Example component we'd pass in props and access the msg content. But Layout isn't doing that.

As it turns out, Layout is still using props, just in a different way. children is actually a special built-in prop. It refers to all of the content inside the Layout tag.

  <Layout>
//ALL OF THIS
    <SEO title="404: Not found" />
    <h1>NOT FOUND</h1>
    <p>You just hit a route that doesn't exist... the sadness.</p>
//TO THIS
  </Layout>
)
Enter fullscreen mode Exit fullscreen mode

Everything between the Layout open and close tags is considered the children prop.

Let's Validate!

So back to our PropTypes validation. Now that we know what the children prop is we can start to understand how we're validating that content.

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}
Enter fullscreen mode Exit fullscreen mode

We can use Layout to wrap any number of things, but the only thing we care about is that we're wrapping something. We can't render a page with no information at all, or at least we don't want to. An empty layout is not what we're after. That's why we have isRequired.

We also want to give a somewhat nebulous definition of what that something may be. The node keyword is just saying, I've passed in something that's renderable. Whatever that is.

Don't Stop at Boilerplate

Keep in mind, this section of the template is ripe for change. As you define your Gatsby application you may want to enforce different standards. For example, you can limit the prop to have one parent element like so.

Layout.propTypes = {
  children: PropTypes.element.isRequired
};
Enter fullscreen mode Exit fullscreen mode

Gatsby gives you this as a starting point to prompt you to use type enforcement and show you what it can do.

And that's it!

Now we understand what this PropTypes code snippet is doing to typecheck our Layout component. As an added bonus we're also more comfortable with the built-in children prop.

As always, too often we see throwaway lines of code inside frameworks and projects that we don't take the time to understand. I encourage you to curiously explore everything you see! It'll make you a better programmer.

Look out for more Boilerplate Basics coming soon!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .