Since useAuth is taking off, I wanted to talk about the global state management technique that makes it work. You might find it useful too, or think it's obvious, I was pretty excited when it clicked :)
And when I say useAuth is taking off ...
Yep 🔥
Ok so global state management, how do you do it? You grab Redux or MobX, or maybe Unstated or Constate and you're done. Right?
All those libraries give you a global store to put your data, allow every component to access that state, and manage re-renders. You get some way of updating that state and life is good.
Sometimes there's extra features.
But what if you don't want to learn yet another library? You just wanna share some state between a bunch of components. What then?
Global state without the hassle
The simplest approach is to put global state in your top-level component. Pass it down through props and if you want to change it, pass down some callbacks too.
Works great and gets out of hand real fast. Passing props is cumbersome and you can create a situation where every little update re-renders your entire app.
Here's a better solution 👉 You can share the state
and dispatch
from useReducer
through context and access them with a hook.
I'll explain using useAuth as an example, but the same approach works for anything.
There's 3 parts to this story:
- A context provider component
- A reducer for state
- A hook providing our API
Users render the context provider somewhere close to the root of their app. Similar to a theme provider, Apollo provider, etc.
The provider feeds state from our reducer into the context. When you fire actions on the reducer, state in the context changes, and every component using the useAuth
hook re-renders with new data.
It's pretty great.
AuthProvider
That's our context provider.
The provider initializes auth0
using Auth0's API and configures some properties. Full version supports a bunch of config via props, overwriting defaults, etc.
We call useReducer
to get a state object and the action dispatch function. Initialize state from local storage if you want persistence, or keep it empty to start with.
I recommend defining initial values so your code doesn't have to deal with undefineds.
Our provider renders AuthContext.Provider
and as its value uses the state
object, dispatch
function, and auth0
object.
This was the trick to getting different useAuth
hooks to talk to each other. Using reducer state and dispatch as the context value.
Using AuthProvider
In Gatsby you use the auth provider in gatsby-ssr
and gatsby-browser
to wrap your entire component tree. With create-react-app this goes around your App component, with other frameworks who knows.
The higher up it renders, the more parts of your app share state.
Auth reducer
The auth reducer takes care of state transitions. full file
If you're not familiar with reducers: it's a function that takes the current state and an action, and calculates the next state. Always returning a fresh object.
In our case the login
and logout
actions handle the user model and cookie expiration time. Both actions also save data to local storage so it persists across page reloads.
useAuth hook itself
With heavy lifting moved to the context provider and auth reducer, our useAuth
hook becomes a sort of thin wrapper and API provider. full file
The state management part of useAuth
is that useContext
call. It hooks into the context shared by AuthProvider
and gets access to the state
object and dispatch
method.
That gives any component that uses useAuth
access to the same shared state.
You could use useContext
directly. I prefer using a custom hook because it makes your code easier to read.
What's better, doing this everywhere you want to access some shared state:
Or this
I know what I prefer :)
With a custom hook you can use dispatch
with carefully controlled values internally. Nobody needs to know what's going on. All they need to remember is your convenient API.
✌️
So that's how you can use React hooks to build powerful abstractions on top of global state shared by all.
What do you think?
Cheers,
~Swizec
Continue reading about useReducer + useContext for easy global state without libraries
Semantically similar articles hand-picked by GPT-4
- React context without context, using XState – CodeWithSwiz 14, 15
- useAuth – the simplest way to add authentication to your React app
- How to use React Context effectively
- Delightful state management with hooks and Constate
- Swap useReducer with XState – CodeWithSwiz 13
Learned something new?
Read more Software Engineering Lessons from Production
I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.
Subscribe below 👇
Software Engineering Lessons from Production
Join Swizec's Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.
"Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️