Loading video player...
All right, now that we have seen how
context helps us eliminate prop
drilling, there is one more piece we
need to talk about. In most React
applications, you don't just want to
read values from context. You almost
always need to update them, too. And
those updates often come from components
that are nowhere near the top of your
application. Think about a theme toggle
in a settings panel, a log out button
inside a user menu, or a language
switcher sitting in a footer. These
components are usually buried several
levels deep, but they still need to
change data that affects the whole
application. Right now, our context only
provides readonly data. Avatar can show
the user's theme, for example, but if it
wanted to change the theme, it couldn't.
The user object is static. So to make
context truly useful, we need to combine
it with state. Let's start by updating
our app component. So it uses use state
instead of a hard-coded object. At the
top, import use state from React and
pass in this user object as the initial
value to use state. The hook returns two
values which we can dstructure using
array dstructuring. It returns user and
a function to update user which we will
call set user. Now the user data lives
in state which means it can change. But
we have a new problem. Only the app
component has access to set user. Avatar
can't update anything unless we give it
that setter function. And the way to do
that is simple. We pass both the state
and the setter through context. Let's
update what we are providing. Create a
new const called context value. And this
is going to be equal to an object with
two values. User which is equal to the
state user and set user equal to the set
of function. This is the ESX shorthand
notation. When the key and value are the
same on the user context provider, we
can update value to context value. Now
our context is providing an object that
includes both the user data and the
function to update it. Any component
that consumes this context can now read
and write. The code here works but the
app component is starting to feel a bit
heavy. And in a real project, you might
have more logic here. role changes,
theme persistence, login and logout, all
sorts of functionality. So, let me show
you a cleaner and more scalable pattern,
creating a custom provider component.
So, in the source folder, create a new
file called user context provider.jsx.
And here, we'll build a provider that
encapsulates all the state logic. import
use state from react as well as the user
context from dot / user context. Next,
export a new component called user
context provider. So, export const user
context provider and this is equal to an
arrow function. It will receive a
children prop which we will destructure
and return the user context. And this is
the provider that provides values to all
the nested components inside. So specify
children. Inside the component, we'll
create the state and the setter
function. The value is user. The
function set user and the initial value
is the same object name Bruce Wayne
admin and theme dark. We will pass the
state and the setter function to the
user context provider as values. User
context value is equal to an object with
user and set user as the key value
pairs. So this component user context
provider now manages its own state and
provides both the value and the update
function. Let's also update the default
context value to match the shape we are
actually using a user object. So user
object with name, role and theme as well
as set user which is a function. Now the
app component becomes much simpler. We
can remove user context, remove the
state management, the context value, the
user context component use state and
simply wrap this with user context
provider component we just defined. All
the state logic is tucked away inside
user context provider and app simply
wraps its children in it. All right, now
let's use this. Let's go back to
avatar.jsx
and add a button that toggles the theme.
User context now returns an object with
user as well as the setter function set
user. We can define a new function
called toggle theme. This is an arrow
function. This will call set user
passing in an object. We spread the user
object to maintain the current values
and update just the theme to user dot
theme. And if this is equal to dark, we
update to light. Else we update to dark.
In the JSX, we can wrap our content with
a div tag. And after welcome user name,
we can add another paragraph current
theme. This is going to be user theme.
and a button that says toggle theme and
on click call the toggle theme function.
Let's save the file and test this in the
browser. You can see our updated JSX
welcome Bruce Wayne current theme dark
and we have a toggle theme button. Click
the button and the theme flips between
dark and light each time we click the
button. Avatar which sits four levels
deep in our component tree can now
update data that lives at the top of the
application and within pass a single
prop to make this happen. This is the
power of combining context with state.
Any component no matter how deeply
nested can read and update shared data
and this pattern passing both state and
its setter into a context is extremely
common in React applications. You will
even see multiple context providers in a
single application. One for
authentication, one for theme, one for
user preferences. It really is up to you
how you want to structure your
application. And just as a side note,
everything we have done here works with
use reducer too. Instead of passing user
and set user, you would pass state and
dispatch. You can even create two
context providers, one for state and one
for dispatch. You can find an example
for that in the React docs. But the key
takeaway here is that our context is no
longer static. It is dynamic, editable,
and accessible from anywhere in the
component tree without prop drilling.
Github - https://github.com/gopinav/React-19-Tutorials Become a Fullstack Developer with Scrimba - https://scrimba.com/fullstack-path-c0fullstack?via=Codevolution Follow me + Twitter - https://twitter.com/CodevolutionWeb Business - codevolution.business@gmail.com React 19 Context with State