Making pageContext available to child components in Gatsby with react-intl

Table of Contents

1. Background

Check out my portfolio, GitHub, or add me on LinkedIn to get in touch. I'm always looking for new connections or feedback!

I'm currently based out of Japan which means that, when it comes to web development projects, I sometimes have to deal with bilingual websites. When building a static website with HTML, CSS, and JavaScript, it's as easy as creating a new HTML file for each page, copy pasting a basic structure, and pasting in the Japanese copy.

But what happens when you want your website to be more dynamic? What if you want to take advantage of the performance benefits that some frameworks offer? This is a challenge I faced recently when migrating a static website I'd made as a freelance project to Gatsby.

Sure, an argument could be made that going the framework route for static websites might be overkill, but there are a lot of benefits that platforms such as Gatsby have to offer.

If you're into social impact and making a difference, head over to the static website to learn more about Socious. Also Feel free to check out the (work-in-progress) Gatsby website or have a look at the GitHub repo to see how everything fits together.

2. The Problem

If you, like me, are looking for a way to create dynamic, multilingual websites using Gatsby then I'd fully recommend react-intl. Installation is easy, the example code is clear and their explanations are great. There was one problem I faced as a beginner:

The problem is that part of the functionality react-intl, particularly the SimpleLocalize component, relies on the page's context to derive the current language. This helps determine which text to use and which links to follow but if your page is broken down into separate components like mine then you're likely going to run into this error.

3. The Solution

It might seem fairly obvious but as a relative beginner to Gatsby and React it took me longer than I'd care to admit. After an embarrassing amount of Googling and digging through Stack Overflow I had a moment of clarity: what if the my page's child components didn't know the page context?

I'd just assumed that, because they were being rendered on the page, that they would automatically have access to the information that SimpleLocalize needed, which wasn't the case.

Sure enough, in the end it was as easy as passing down the props of the main page component to the child components and everything came together. I elected to pass all of the page's props using the spread operator ({...props}) but if you're committed to fine-tuning for performance feel free to destructure what you need.

In the end, this is the body of my parent (homepage) component:

const IndexPage = (props) => {
  return (
    <Layout>
      ...
      <AppLinks {...props} />
      ...
    </Layout>
  )
}

And here's how I implemented it in the child component:

const AppLinks = (props) => {
  return (
    <SimpleLocalize {...props}>
      ...
      <FormattedMessage
        id="app-links-header"
      />
      ...
      <FormattedMessage
        id="app-links-subheader"
      />
      ...
    </SimpleLocalize>
  )
}

Sidenote

For each level of nested components you'll need to pass the props along. For example, I had three layers:

- index.js
-- Intro.js
--- EarlyAccessForm.js

Follow the same process at each step and you'll have a working chain of components.

In Intro.js:

<EarlyAccessForm {...props.pageContext} />

And in EarlyAccessForm.js:

...
render() {
  return (
    <SimpleLocalize {...this.props}>
...

I used {...this.props} since EarlyAccessForm is a class-based component but to use it in a functional component just change {...this.props) to {...props}.

And voila, dynamic copy rendered based on the page's current language setting!

And there you have it. If you've worked with react-intl before and have any suggestions, feel free to drop them down in the comments!

19