Context is an alternative way to share data across the components in React applications. In a simple React application, the data is passed from top to bottom via props. As the application grows in scope and features it becomes increasingly difficult and annoying to be constantly passing down the props.
We often may come across the term ‘props drilling’, which means passing down the data through many levels to its final destination. Context helps us manage this complexity. It provides a way to pass data around directly.
Context should be storing data that can best be described as ‘global’ and that is passed down in one direction (from top to bottom). Good examples would be theme or user data, as those are required quite often.
Creating Context
I have just started a new project using create-react-app for demonstration purposes.
We are going to start by defining a dummy user in our app.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
const dummyUser = {
name: 'Tommy',
age: 24,
hobby: 'coding'
}
ReactDOM.render(<App />, document.getElementById('root'));
The next step is to create the context itself
import React, { createContext } from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
const dummyUser = {
name: 'Tommy',
age: 24,
hobby: 'coding'
}
export const UserContext = createContext();
ReactDOM.render(<App />, document.getElementById('root'));
As you can see I have imported the createContext function from react. I then call the function and save the output object into the variable called UserContext. It’s important to give our context variables meaningful names to reflect their true purpose. In our case, it’s going to be holding some data about the current user, so it makes total sense to name it UserContext.
Now we need to use the related Provider to enable the use of our context across the application.
import React, { createContext } from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
const dummyUser = {
name: 'Tommy',
age: 24,
hobby: 'coding'
}
export const UserContext = createContext();
ReactDOM.render(
<UserContext.Provider value={dummyUser}>
<App />
</UserContext.Provider>,
document.getElementById('root')
);
The Provider component comes with the newly created UserContext. We then need to wrap the entire tree structure of our application to enable it across all of the components.
Using Context
To demonstrate the fact that context can be used anywhere in the component tree structure we are going to make a slight modification to the App.js component.
import User from './User'
function App() {
return (
<div style={{ margin: '50px' }}>
<h1>Currents user is:</h1>
<User />
</div>
);
}
export default App;
As you can see App.js is importing another component called User.
import { useContext } from 'react';
import { UserContext } from './index';
const User = () => {
const user = useContext(UserContext)
return (
<>
<p>Name: {user.name}</p>
<p>Age: {user.age}</p>
<p>Hobby: {user.hobby}</p>
</>
)
}
export default User;
As you can see User is two levels lower in the tree structure and we can still use the dummy user data.
We are importing the useContext hook that’s gonna help us get the data we want. The hook accepts the context object returned from the createContext and returns the value that was passed to its Provider. In our case, we passed there the dummyUser object. We then use its properties and render them to the page.
You may have also heard about Redux at some point in your time as a developer. It’s a state management library that builds on the concepts we just introduced. Make sure to check out Osman’s article on how to use it.
💬 Leave a comment