Understanding State Management in React: A Comprehensive Guide to Global State and Context API

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Next.js Complex State Management Patterns with RSC course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Next.js Complex State Management Patterns with RSC, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Next.js Complex State Management Patterns with RSC
  • [00:00 - 00:08] Alright, welcome to lesson four of the module about state management. Today's focus is going to be handling global state.

    [00:09 - 00:26] Global state is vital for any data that multiple components within your application need to access or even manipulate, such as user authentication status or even like the current theme for your application. So we've hinted at different ways to do that.

    [00:27 - 00:34] So now in this video we're going to go deep how to use that and some bad practices that you want to avoid. So let's go.

    [00:35 - 00:51] So unlike local state, global state is not defined just within one component. It actually spans across multiple components often requiring either a common ancestor or some sort of state management library or architecture.

    [00:52 - 01:12] This state is useful when various parts of your app need to react to the same data. And as I already mentioned previous videos, in this course I'm not going to go deep into state management libraries because they're not really useful when we reach the point of using state with server components as well.

    [01:13 - 01:25] They only stay within the client side. So to fully understand how they work and what tools we're going to be using in the future we'll stick to the context API which is what I want to talk about now.

    [01:26 - 01:47] So when it reacts patterns for global state is the context API. It bypasses the need for prop drilling essentially which would imply passing down props from pairing components into child components down the hierarchy until the actual component that needs the prop or the state value can use it.

    [01:48 - 02:08] So imagine something like on screen right now, this is trying to represent a poorly architected page that is not using the context API to share global state across multiple components. So the only tool that we have if we're not using context API or any third party library is prop drilling.

    [02:09 - 02:19] So each of these big rectangles that you see here is a single component. Since they need to directly pass props down from parent to child.

    [02:20 - 02:42] Each of them is forced to use or to instantiate the child within their code. So you end up with a page that defines a navigation bar component but then this component also needs to instantiate the content of the page within it instead of having it at the same level as a completely different component.

    [02:43 - 03:09] So in this case the user profile is being instantiated within the net bar and it all starts at the highest level, the layout component, essentially the most generic component. It grabs somehow the login state in let's say in this case where the piece of global state that we want to share is the global state and it's being represented in this picture as the little purple circle.

    [03:10 - 03:35] That data needs to be used by the user profile and by the logout button which are all the way down at the bottom of this fake hierarchy that I created. So the only way to do it is to pass down that information through props of these components until the actual logout button component and the user profile component received that information.

    [03:36 - 04:04] This is as you can imagine definitely a big bad practice, something that you really want to avoid because you end up forced into a page architecture that is not optimal and because you're coupling components that should not be coupled. In our case the navigation bar should be an individual component that has to seat at the same level as the user profile for example and could potentially be updated without having to affect the content of the page.

    [04:05 - 04:16] The same goes for the logout button which should be able to be used everywhere else on the application. Here we're coupling an entire set of components simply because they have a common need.

    [04:17 - 04:25] The understanding whether the user is logged in or not. This is something that is easily solved by what is known as the context API.

    [04:26 - 04:45] So let's look into that. So through this API which is provided by React you create a context provider which will wrap a number of components down the hierarchy and every component wrapped by this provider has direct access to a set of exported properties.

    [04:46 - 04:53] So let's not get confused by terminology or anything else. This is essentially another component that you define.

    [04:54 - 05:13] A special type of component that instead of having to return HTML is just returning a set of specific components that React will understand and utilize to know who needs to access what type of global state. Again that is behind the curtain you don't really care about that.

    [05:14 - 05:32] All you care about is that your provider is a normal React component that has a local state that can be shared through React and made global essentially. So now only components that need access to the global state will import and use these values.

    [05:33 - 06:16] These values by the way can be just state values, your state variables or any type of function that you want to define and export that deals with those values essentially either by providing some kind of calculations around them or even allowing other components to modify it which is kind of the neat trick that the context API allows you to do . So in the wrapper here that we're seeing, the app wrapper which is called, we're defining a local state, the user state and the accompanying setter function and then we're just defining the user context provider which sets the value of essentially an object that has these two properties, the user and the set user functions.

    [06:17 - 06:29] And that is it. Now React knows through this process that any component within the hierarchy that doesn't really mean just the app component by any component used within the app and so on and so forth.

    [06:30 - 06:45] They will have access to consuming this particular context and by consuming it they'll be able to use either the user state variable directly or accessing the set user function and call it directly. Here's how you consume your context essentially.

    [06:46 - 07:11] The user profile component here is using the useContext hook and is referencing the user context that we created before. Now the useContext hook is going to return the value object that we defined before and here what you're seeing is instead of array destructoring like with the useState hook, this is object destructoring essentially.

    [07:12 - 07:36] We're grabbing the returned object from the useContext hook which had two properties, user and setUser and we're just keeping the user property. We're ignoring for this particular case, we're ignoring the other one and we're keeping the user property and we're assigning it into a constant also called user and then we're simply using it as part of the return value.

    [07:37 - 07:53] Nothing really needs to change here. So the neat thing about this is that if somewhere else on your application through the context provided you also update the user, the user profile if you have it open as well will immediately be re-rendered and updated.

    [07:54 - 08:27] That is because now you have linked your component to a central repository of data essentially you've linked your component to the context provider through the useContext hook instead of having like before coupled the components together. The components are now completely individual and they don't really need to know about each other but they do know of the central store of state information and whenever that information is updated every other component that is using it is also going to be updated.

    [08:28 - 08:46] You can think of the top level provider we saw as a broadcaster of the global state. Any child component that is consuming it will directly have access to that state without any intermediate props or without having to use any other components in the middle.

    [08:47 - 09:05] That's the beauty of the context API. It really simplifies the concept of global state to a point where you can create your context provided to be as complex as you want but it's also giving you the flexibility of creating very simple one that shares some basic data without the need of adding any external third party libraries or dependencies.

    [09:06 - 09:25] So to recap a global state is essentially meant for sharing dynamic data across your application. The context API simplifies this by saving you from prop drilling which is about practice as we saw and keeping your components and architecture and especially the page architecture clean and simple.

    [09:26 - 09:47] So remember to elevate state into the global status only when necessary. Don't overcomplicate your logic and use the context API whenever one or more components need to share data but only then if you see that you're using the context API for something that only one component is using then you're probably doing it wrong and you're probably elevating local state into global status whenever it's not needed.

    [09:48 - 09:53] Remember that and look to that. So that's it for the state management module.

    [09:54 - 10:02] In the next one we're going to start looking into client components, how they are defined and really what's the use case for them. In the meantime keep coding and I'll see you then.