Sometimes when creating a SPA with React, you realize you need some global variables. The easiest way to make values available at all levels of a complex ReactJS application is to use a Context. The following is an example of creating a React SPA with a single global context that shares values at all levels of the component tree. I give two examples of using the context. One is a class based React Component and the other is a function based React Component.
I used npx to run create-react-app . Then I added contexts and components folders and the following files to my React src folder.
Here is the code I added.
MyContext.jsx … First you need a context.
1 2 3 4 5 |
import React from 'react'; const MyContext = React.createContext(null); export default MyContext; |
MyContextProvider.jsx … I have a Consumer defined at the bottom, but am not using it. I expose one variable and one function through the context. This is just so you have an example of doing either.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import React, { Component } from 'react' import MyContext from './MyContext' class MyContextProvider extends Component { constructor(props) { super(props) this.state = { greeting1: 'Hi there!' } } greeting2 = (name) => { return "Hi there, " + name + "!"; } render() { const {children} = this.props; return ( <MyContext.Provider value={{ //methods and state to provide oneGreeting: this.state.greeting1, twoGreeting: this.greeting2 }}> {children} </MyContext.Provider> ) } } export const MyContextConsumer = MyContext.Consumer; export default MyContextProvider; |
index.js … Once you have a context provider exported with something in the context to use, make it global by adding it to the index.js file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import MyContextProvider from './contexts/MyContextProvider'; ReactDOM.render( <React.StrictMode> <MyContextProvider> <App /> </MyContextProvider> </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); |
MyClassComponent.jsx … This is an example of accessing the global context from a class component in React.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import React, { Component } from 'react' import MyContext from '../contexts/MyContext' export class MyClassComponent extends Component { constructor(props) { super(props); this.state = {count: 0};//count is just an example } static contextType = MyContext; render() { const greeting = this.context.oneGreeting; return ( <div> <h1>Class Component</h1> <p>{ greeting }</p> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({count: this.state.count + 1})}>No! Click me!</button> </div> ) } } export default MyClassComponent |
MyFunctionalComponent.jsx … This is an example of accessing the global context from a function component in React.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import React, {useState, useContext} from 'react'; import MyContext from '../contexts/MyContext'; const MyFunctionalComponent = () => { // "count" is an example state const [count, setCount] = useState(0); const values = useContext(MyContext); return ( <div> <h1>Function Component</h1> <p>You clicked {count} times</p> <p>{ values.twoGreeting('Bob') }</p> <button onClick={() => setCount (count + 1)}> Click ME!!!</button> </div> ); } export default MyFunctionalComponent |
App.js … The two components could be used at any level of the tree, but I added them to App for simplicity of this example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import './App.css'; import MyClassComponent from "./components/MyClassComponent"; import MyFunctionalComponent from "./components/MyFunctionalComponent"; function App() { return ( <div className="App"> <header className="App-header"> <MyClassComponent /> <MyFunctionalComponent /> </header> </div> ); } export default App; |
That’s it. You have two Components using a global context.