React’s Context API

React’s Context API

React’s Context API is a powerful tool that became fully supported and documented with react 16.3.1. The Context API provides a way to share values and functions between components without having to explicitly pass each value and function through every level of the tree, also known as ‘prop drilling’. (from the official Docs.)

What is Prop Drilling?

example from CWDS CALS project:

Through leveraging the power of the context api, it is possible to create top level global stores that allow the managing of values and their functions throughout the app.

The context API consists of three main elements:

  1. Creating Context: ‘context’ is created via the react.createContext() function. This returns the Provider and Consumer objects that will be used to provide and consume the data within.
  2. The Provider: This is where the data lives. It’s a store of the context’s relevant values and functions. Note: The provider must be at a higher level in the component tree than the consumer.

3. The Consumer: This is where data is accessed. The consumer accepts a prop called “children” which must be a function that accepts the value and must return a react element.

  • Note: Thereact.createContext() function also can take an argument, defaultValue. defaultValue is used when a Consumer does not have a matching Provider above it in the tree.

Here is a s simple example to examine these three elements:

const ExampleContext = React.createContext('') 
// this creates an ExampleContext.provider, ExampleContext.consumer
class ExampleProvider extends React.Component {
state = {defaultValue: 'default'}
render() {
return (
value={this.state}>
{this.props.children}

)
}
}
class App extends React.Component {
render() {
return (


{value =>
{value}

}


)
}
}

Demonstration

begin by creating a new app:

npx create-react-app context_example_app

running yarn start and opening localhost:3000 in the browser will bring up the default create react app homepage. (Before continuing, check the project’s package.json and make sure that the correct version of react-dom@16.3.1 and react@16.3.1 are installed and update as needed.)

The output of this demonstration will be a simple app that demonstrates how to pass state and management and avoid prop drilling using the context api:

clicking the button will change the superPower

Here is a look at the source directory:

Before taking a look at app.js Begin with creating the context.

import React, { Component } from 'react';
export const SuperPowerContext = React.createContext();
export class SuperPowerProvider extends Component {
state = {
name: 'John Doe',
superPower: 'X-RAY VISION'
}
changePower = (power) => {
this.setState({superPower: power})
}
removePower = () => {
this.setState({superPower: 'none'})
}
changeName= (newName) =>{
this.setState({name: newName})
}
render () {
return (
state: this.state,
actions:{
changePower: this.changePower,
removePower: this.removePower,
changeName: this.changeName
}
}}>
{this.props.children}

)
}
}
export const SuperPowerConsumer = SuperPowerContext.Consumer

superPowerContext.jsx contains all actions that occur within the context of superPowers. Most important is the value prop on the superPowerProvider:

  • This value prop can accept objects and functions.
  • These functions relating to the context are defined in the context file.
  • Initial state is also defined.

Next take a look at superPerson.jsx, which is consuming this provider:

import React, { Component } from 'react'
import {SuperPowerConsumer} from './superPowerContext.jsx'
export class SuperPerson extends Component {
state={}
inputRef = React.createRef()
render () {
return (


{(context) => (

Name: {context.state.name}


superPower: {context.state.superPower}


ref={r => (this.inputRef = r)} />



)}


)
}
}

here we import the consumer object created in the context file, and wrap all components in it. Notice how the functions used to change state are defined and implemented in the superPowerContext.jsx rather than the leaf component in a tree, or higher up and then passed down as props.

Next, take a look at the intermediary component, superFriends.jsx:

import React from 'react'
import {SuperPerson} from './superPerson.jsx'
export const SuperFriends = (props) => (



)

This is a simple functional component meant to illustrate how the context api allows the removal of prop drilling.

Lastly, superFriends.jsx is added to app.js. and wrapped in the superPowerProvider imported from the superPowerContext.jsx file.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import {SuperPowerProvider} from './superPowerContext.jsx'
import {SuperFriends} from './superFriends.jsx'
class App extends Component {
render() {
return (


logo

Welcome to React









)
}
}
export default App

What is vital here is to wrap this middle component, superFriends.jsx in the SuperPowerProvider. this is what allows the consumer, several layers down, without providing intermediate props, to have access to the methods and values within superPowerContext.jsx.

what is react.fragment?

  • its a simple way to replace having to use divs in between multiple components. (docs)

Conclusion

React’s newly supported context api is a clean solution to simple prop drilling cases and and creating top level stores without having to implement larger libraries like redux.

Further Reading

The below links are great for learning more about the context api (besides the docs!):

“React’s Context API” Posted first on ” JavaScript on Medium “
Author: keith lauher

Author: Pawan Kumar

Leave a Reply

Close Menu
%d bloggers like this:
Skip to toolbar