Bite-sized screencasts for React
and frontend developers

What can React Context API do for you? Multi-language text, Modals, and Theme switchers

posted on: 24-may-2018

react context example1 I am lazy, by default. Learning something new takes effort and time. So, I always start by asking “why should I learn this? How this insert here: framework, library, programing language will make my life easier?”

A few weeks ago I’ve published a tutorial and screencast about how to use the new React 1.6 context API. It seems that also some of the js-craft readers are lazy as well. In a good way, of course :). We received a few emails sounding like: “ok, this React Context is nice, but how can it benefit me in real applications? How can I put React context to work?”.

It turns out that React Context can be used as a great tool for managing “stuff” at a global level of our application. Things like - if we have modals opened or not, multi-language support, identity management or switching a theme for our site, are perfect fits for the React Context. In these types of situations, it does not make sense to go through all the trouble of setting up full state management libs like Redux or Mobx.

If this is your first encounter with the Context API in React, it may be a good idea to read first about how to use it. The official guide is here and, as said earlier, we also have a short tutorial about it.

So, let’s see in action some of the use cases for React Context:

Building a Multi-language site with React Context

Having our app or site support multiple languages is a tedious task that usually gets pushed to the bottom of the to-do list. But, for simple things like landing pages or apps that are not very text dependent, React Context can be a great tool.

Below you have a codesandbox with our simple example:

This for sure can be improved. Please keep in mind that this is just a proof of the concept.

The core component here is the simple TranslatableText. It takes a dictionary as a property and, based on what it receives from the LanguageConsumer, it will show the message in the corresponding language:

const TranslatableText = props => (
  <LanguageConsumer>
    {({ language }) => props.dictionary[language]}
  </LanguageConsumer>
);

// and to create a TranslatableText
<TranslatableText dictionary={{
  french: "Bonjour, Michel!",
  english: "Hello, Michael!",
  italian: "Ciao, Michele!"
}}/>

Of course any of this will not work if we do not have in place a React Context mechanism. First, we will create the building blocks - the LanguageContext and the LanguageConsumer:

const LanguageContext = React.createContext();

const LanguageConsumer = LanguageContext.Consumer;

Having them created, we can now make the LanguageProvider. It is a standard React component, that stores the current language of the App and a method to update this language:

  class LanguageProvider extends React.Component {
    state = { language: "french” };

    updateLanguage = e => this.setState({ language: e.target.value });

    render() {
      return (
        <LanguageContext.Provider value={{
          language: this.state.language,
          updateLanguage: this.updateLanguage
        }}>
          {this.props.children}
        </LanguageContext.Provider>
    );}
}

It will wrap the whole app so it can expose the language and the changeLanguage method to any descendant tag via the LanguageConsumer:

const App = () => (
  <LanguageProvider>
    <div>
      //...
    </div>
  </LanguageProvider>
);

And now we can trigger the updateLanguage in the header:

const Header = () => {
  return (<LanguageConsumer>
    {({ updateLanguage }) => (
      <header> see this site in:
        <select onChange={updateLanguage}>
          <option value="french">french</option>
          <option value="english">english</option>
          <option value="italian">italian</option>
        </select>
      </header>
    )}
    </LanguageConsumer>);
};

Managing Modals with React Context

At the first glance having a modal appearing in a React application, it’s an easy win. It should not need any React Context fancy stuff. But, when your app will start to grow bigger and more complex, and the modal state is all over the place, then the React Context starts to make sense.

Below you can see the an example of how to use a React Context to manage Modals:

All the magic takes place into the Provider component. It will decide if we should have a modal opened and will use the Modal wrapper component to display the ModalContent.

class Provider extends React.Component {

  showModal = (content, props = {}) => {
    this.setState({
      Content,
      props
    });
  };

  hideModal = () =>
    this.setState({
      content: null,
      props: {}
  });

  state = {
    content: null,
    props: {},
    showModal: this.showModal,
    hideModal: this.hideModal
  };

  render() {
    const ModalContent = this.state.content;
    return (
      <ModalContext.Provider value={this.state}>
        {this.props.children}
        {ModalContent ? <Modal content={ModalContent} /> : ""}
      </ModalContext.Provider>
    );
  }
}

One of the nice parts is that the "design" of this system allows us to fully customize what gets into the content of the Modal. When you trigger the creation of a modal you will need to pass in a React component. This can be any HTML we need, like a simple text, an image or anything else.

const TextModalContent = () => (
  <div>
    <h1>Text modal</h1>
    <p>Some next here !</p>
    <CloseButton />
  </div>
);

const ImageModalContent = () => (
  <div>
    <img src="https://media.makeameme.org/created/take-a-break-09utnz.jpg" />
    <CloseButton />
  </div>
);


//...
<button onClick={() => showModal(TextModalContent)}>Open Modal</button>,
<button onClick={() => showModal(ImageModalContent)}>
Open Image Modal</button>

The Modal component only serves as a wrapper for some CSS classes, in order to make something to look like a modal.

const Modal = props => {
  const Content = props.content;
  return (
    <div className="modal">
      <div className="modal-content">
        <Content />
      </div>
    </div>
  );
};

For sure you can improve this example by having things like callback functions for the modal’s modals’ ok-cancel buttons, or parameters that could customize some modal templates. But, for beginning, I think it's a good start.

You can read here a nice article about React Context and Modals. I’ve used it as an inspiration for this article :)

Making a Theme switcher with React Context

I’ve always liked how apps like Twitter or Feedly give you the opportunity to select if you want to change a light or dark color scheme.

react context api example

And guess what!? It’s quite easy to implement this with the React Context:

This is the most straightforward one out of these three examples. First, we will need to define two CSS classes that will contain the rules for how the app will change based on the selected theme:

.day {
  color: black;
  background-color: white;
}

.night {
  color: #5692e6;
  background-color: #142b41;
}

Following this, the provider will expose the CSS’ class name and a method to toggle it:

  class TProvider extends React.Component {
    toggleTheme = evt => {
      this.setState({ theme: evt.target.checked ? "night" : "day" });
    };

    state = {
      theme: "night",
      toggleTheme: this.toggleTheme
    };
    //..
}

The toggleTheme method will be called when the user changes the status of the Theme slider:

class Slider extends React.Component {
  render() {
    return (
      <label className="switch">
        <TConsumer>
          {({ toggleTheme, theme }) => (
            <input 
              onChange={toggleTheme}
              type="checkbox"
              checked={theme === "night"}
            />)}
        </TConsumer>
//...

And given the fact that theme state value of the Context Provider is set as the className of the main div of our app, this will also update how the app looks like:

  const App = () => (
    <TProvider>
      <TConsumer>
        {({ theme }) => (
          <div className={theme}>
          <h1>React Context</h1>
//...

For sure you can also find other practical applications for React Context. However, keep in mind that React Context is a feasible solution mostly for lightweight cases. React context it’s not (or at least not yet) designed to be a complex state management solution. There are cases in which your app will benefit from Redux or Mobx, but for simple stuff, it does not make sense to add that extra code and you can just use the built in React Context.

I hope you enjoyed this article and if you would like to get more articles about React and frontend development you can always sign up for my email list.