BBV logo

Advanced React Patterns 2 - Let’s talk about Provider

Jonatan Salas

Dec 09, 2017 - 2 min read

The Provider pattern is used mostly to share data across the tree descendant nodes in a React application.

This pattern involves the usage of the React Context API. Imagine the context as a big global object variable that everyone can access by defining an specific static class field called contextTypes.

Inside of contextTypes object you will need to declare the keys properties of the object that you want to retrieve. It’s usage is not recommended due to it’s experimental behavior, the context api may change in a future.

There’s an open RFC spec to define the future behavior of context.

Most of the libraries you maybe use like react-router, redux, mobx, material-ui, and others use the Provider pattern.


 Perfect Use Cases

The Provider Pattern is perfect to supply the following use cases:

  • Theming — Pass down app theme
  • i18n — Pass top-down translations messages
  • Configuration — Pass down generic configuration
  • Implement Publish/Suscribe Pattern — Like redux does
  • Implement Observer/Observable Pattern — Like mobx does
  • Implement Channel Pattern

 Example Case — App Theming

In the following example you will see how to implement Provider Pattern to supply a theme object to child components.

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

class ThemeProvider extends React.Component {
  static displayName = 'ThemeProvider';

  static childContextTypes = {
    theme: PropTypes.object,
  };

  getChildContext = () => ({
    theme: this.props.theme,
  });

  render() {
    return this.props.children;
  }
}

class ThemableButton extends React.Component {
  static displayName = 'ThemableButton';

  static contextTypes = {
    theme: PropTypes.object,
  };

  render() {
    const { children, ...buttonProps } = this.props;
    const style = this.getStyles();

    return (
      <button {...buttonProps} style={style}>
        {children}
      </button>
    );
  }

  getStyles = () => {
    if (this.context.theme) {
      return this.context.theme.button;
    }

    return null;
  };
}

const App = () => (
  <ThemeProvider
    theme={{
      button: {
        backgroundColor: '#414141',
        color: '#FFFFFF',
        width: 150,
        height: 25,
      },
    }}
  >
    <ThemableButton onClick={ev => alert('Clicked!')}>Hola</ThemableButton>
  </ThemeProvider>
);

ReactDOM.render(<App />, document.getElementById('root'));

This is the Second post from a series I decided to share, first one is here.

Jonatan Salas

Co-Founder and CEO at BlackBox Vision

Subscribe for latest updates

Sign Up for our newsletter and get notified when we publish new articles for free!

arrow back iconPrevious