React Suspense comes handy when you want to show an indication to user that something is loading in your app. Loader is the simplest example for a Suspense component. Let’s deep dive into the details of Suspense.
Traditionally, you pass information from a parent component to child component via props in React. But data passing through this props drilling can make your code verbose and inconvenient if you have more components in the middle, or if many components in your app need the same information.
For solving this, in V.16.3 React introduced Context and it helps you to share data to any component with out passing it explicitly through props. This context can be used to manage the global data such as user info, theme preferences, settings, and much more.
In this post, you’ll learn how to use the context in React.
Creating the Context
According to the React docs, React Context provides a way to pass data through the component tree from parent to child components, without having to pass props down manually at each level.
To create a Context, you must import createContext
function from React and intialize it with default value, if nothing to initialize you can specify null
. The default value will use if there is no matching context provider in the tree above the component that reads context. The default value is static and never changes with time.
// ThemeContext.js
import { createContext } from "react";
const ThemeContext = createContext({
theme: "light",
toggleTheme: () => {},
});
The createContext
function will return a context object and it does not hold any information. It is a representation of context which other components read or provide. Typically, someContext.Provider
in components will provide the context values and you can access these values by using useContext(someContext)
in other components.
Providing the Context
By using someContext.Provider
you can wrap the components and pass the context value to the components inside. By passing context value through this Provider
, all the components inside the Provider
can access the value, no matter how deep the components are. You can pass values with any type through the provider as shown below.
// ThemeContextProvider.js
import { ThemeContext } from "./ThemeContext";
function ThemeContextProvider({children}) {
const [theme, setTheme] = useState("light");
// ...
const cnxtValue = {
theme: theme,
toggleTheme: handleToggleTheme,
};
return (
<ThemeContext.Provider value={cnxtValue}>
{children}
</ThemeContext.Provider>
);
}
Consuming the Context
Consuming the context in the component can be acheived with React hook useContext
. Through the useContext
you can read and subscribe to context from your component.
You can call useContext
in the top your component and pass the context that you have created previously with createContext
. It will provide the value passed through by someContext.Provider
. If there is no values available, it will return the defaultValue
intialized by the createContext
. React will automaticlaly re-render all the components that use a particular context if any value is changed in the context.
// Page.js
import { useContext } from "react";
function Page() {
const { toggleTheme, theme } = useContext(ThemeContext);
// ...
}
Where to use Context
The main idea of using Context is to access global data and re-render the components when the global data is changed. It can help you to avoid props drilling and make your code more effective.
Below are the some of the usecases for React Cotext:
- global state
- application configuration
- theme settings
- user information
- authentication details
- routing
How to use Context
Below you can find a simple application have a theme switching button to show how we can use React Context. Here we are setting the default values with createContext
, passing the theme data to components by using Provider
, and finally accessing the data in the components by using useContext
.
ThemeContext.js
import { createContext } from "react";
export const ThemeContext = createContext({
theme: "light",
toggleTheme: () => {},
});
ThemeContextProvider.js
import { useState } from "react";
import { ThemeContext } from "./ThemeContext";
export default function ThemeContextProvider({ children }) {
const [theme, setTheme] = useState("light");
function handleToggleTheme() {
if (theme === "light") {
setTheme("dark");
} else {
setTheme("light");
}
}
const cnxtValue = {
theme: theme,
toggleTheme: handleToggleTheme,
};
return (
<ThemeContext.Provider value={cnxtValue}>
{children}
</ThemeContext.Provider>
);
}
Page.js
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext.js";
export default function Page() {
const { toggleTheme, theme } = useContext(ThemeContext);
return (
<div id="app" className={theme}>
<header>
<h1>Context Demo</h1>
<button onClick={toggleTheme}>Toggle Theme</button>
</header>
<article>
<h2>Context in React</h2>
<p>
This example will show you to use Context!
</p>
</article>
</div>
);
}
App.js
import ThemeContextProvider from "./components/theme/ThemeContextProvider";
import Page from "./components/theme/Page.jsx";
function App() {
return (
<ThemeContextProvider>
<Page />
</ThemeContextProvider>
);
}
export default App;
In the above example you can see, when we are clicking the theme toggle button the state is changing and page component is re-rendering immediately to switch the theme.
The React context is stateless by default and it doesn’t provide any dedicated method to update the state. For updating the state you can use hooks like useState
or useReducer
. In the above app, the components use useState
to switch the theme between light and dark.
Summary
- By using React Context you can avoid props drilling and manage global state
- Using the context requires three steps: Creating, providing, and cosuming context.
- You can handle the state with hooks like
useState
oruseReducer
in context.
Example Repository
Check out the full working examples in the GitHub Repository.
References
React Doc, React Doc, Telerik, React legacy, Log Rocket, Dmitri Pavlutin
What are your thoughts on this post?
I’d love to hear from you! Click this link to email me—I reply to every message!
Also use the share button below if you liked this post. It makes me smile, when I see it.