DEV Community

Cover image for Context in React
Sahil for Margarita Humanitarian Foundation

Posted on • Updated on

Context in React

What's this Context in ReactJS everyone's talking about! So according to the React Documentation " Context provides a way to pass data through the component tree without having to pass props down manually at every level."

So we can see it's a way to pass data through the component tree without props at every level. Well isn't it amazing! because it's like having global variables or in react terms something like global props. Let's take an example and go through the Context with React to get a good idea about it.

Very simple usage for such a feature might be using Themes (Dark Theme/Light Theme) for your React Application (NOTE: We must use Context for only the states which would not change regularly). As themes are supposed to be passed to various components to change their appearance on say a click of a button anywhere in the component tree.

Now if we had usual props used to pass the data we might end up in trouble why? Let's say we have one application with a main component within it a brand component and a cards section inside it as shown below:
React App Structure

Now say you have a state maintained in Main Component and then use in cards section so you would have to pass it down all through from main to display and then get it in Cards component. This is a very basic structure and this approach is not very practical in web applications with complex structures.

That's where the React Context comes to the rescue. Context provides a very simple structure for this purpose. Let's walk through the steps for using Context:

  • You might have to create a context that we are gonna use for storing the global props and you might wanna do it in a separate component (For example here a theme Context is created).
 const ThemeContext = React.createContext(); 
Enter fullscreen mode Exit fullscreen mode
  • Then you have to create a ContextProvider component which would wrap all the components of the app and it must contain all the states that are to be passed to each and every component which is wrapped in it.
export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');
  const [backgroundColor, setBackgroundColor] = useState('bg-gray-100');
  const [textColor, setTextColor] = useState('black');
  const [cardsBackgroundColor, setCardsBackgroundColor] = useState('bg-white');
  const toggleTheme = () => {
    if (theme === 'light') {
      window.localStorage.setItem('theme', 'dark');
      setThemeColor('dark');
    } else {
      window.localStorage.setItem('theme', 'light');
      setThemeColor('light');
    }
  };
Enter fullscreen mode Exit fullscreen mode
 return (
    <ThemeContext.Provider
      value={{
        backgroundColor,
        textColor,
        cardsBackgroundColor,
        toggleTheme,
        theme,
      }}
    >
      {children}
    </ThemeContext.Provider>
  );
};
Enter fullscreen mode Exit fullscreen mode
  • Now that's all left is to use Context where we might wanna use it, but before we do that we would require to import Context wherever we want to use it. To keep all the things simple you might wanna expose a custom hook to keep the import of Context minimal.
export const useContextTheme = () => {
  return useContext(ThemeContext);
};
Enter fullscreen mode Exit fullscreen mode
  • Finally Now we want to use our created Context, for that we would require the custom hook created by us in the previous step we import it and we are free to use it however we wish!

Import the context:

import { useContextTheme } from 'components/ThemeContext';
Enter fullscreen mode Exit fullscreen mode

Use inside your component:

  const { toggleTheme, cardsBackgroundColor, theme } = useContextTheme();
Enter fullscreen mode Exit fullscreen mode

Hurray! you are good to go for creating and using your own Contexts!

Discussion (4)

Collapse
peerreynders profile image
peerreynders

sebmarkbage 2018

My personal summary is that new context is ready to be used for low frequency unlikely updates (like locale/theme). It's also good to use it in the same way as old context was used. I.e. for static values and then propagate updates through subscriptions. It's not ready to be used as a replacement for all Flux-like state propagation.

Granted the example shown here deals with "locale/theme" data — the issue is that it would be all too easy to get the impression that it is OK to store "regular data" within context.

For example Redux and MobX simply store an access point that never changes during the entire application session within context.

That (never changing) access point makes it possible to subscribe to updates from the library runtime. Once the subscribed, context is rarely involved in component ⬌ data exchanges.

Collapse
sahilkoun profile image
Sahil Author

I am Sorry, I should have mentioned about the things me might store in Context (like which changes not on regular basis) and the things we might not.

Collapse
peerreynders profile image
peerreynders • Edited on

No need to apologize — for the most part the official docs are silent on the matter and I only became aware of it through Mark Erikson's Why React Context is Not a "State Management" Tool.

Phrased differently: Context is a place for "first introductions" between components and cross-component state (management) but not for "regular meetings" between them.

In my opinion the countless "don't need Redux, just use Context" statements communicate a misunderstanding of what context actually is.

There are "lighter" (cross-component) state management solutions like unistore, valtio, zustand and jotai.

Collapse
lowlifearcade profile image
Sonny Brown

Nicely done. This makes me want to use context more.