Hi everyone. My name is Tanner Linsley, and I'm a co-founder and VP of UI and UX at nozzle.io, where we build SEO rank tracking software for enterprise. I absolutely love React and JavaScript, and I have a bit of an obsession for building open source software as well.
So since learning React, I've been super obsessed with topics like static site generation, data visualization, and animation. But today I'd like to talk to you about what is possibly my favorite one of all, global state management.
Today, a ton of code in our applications is dedicated to consuming and manipulating asynchronous data. Whether that data comes from our users or servers or third party APIs, it's absolutely critical for our apps to provide value to our users. In fact, for a lot of us, our applications are just opinionated user interfaces for consuming and managing this data.
Over the years, I've noticed that patterns around accessing and manipulating our data in our applications have quickly taken up residence with what we all know as global state. Global state is super convenient. It helps us avoid prop drilling, and it lets us access data across our application without copying or duplicating it. And it even helps us communicate between isolated components and hooks that otherwise wouldn't be able to. In the end, it just helps us do more with less code. It's extremely accessible and powerful, so it's only natural that we would want all of our important server side data to be just as accessible as our global state. And with that expectation, it's no surprise that we as React developers have chosen to co-locate our server side data with the rest of our global state.
It's relatively easy to do this by using something like local component state with React context, or even by using any number of libraries from the ever-growing list of global state management tools out there. But in the end, the expectation is usually the same. We expect our global state not only to be able to handle trivial things like menu state, themes, things like toasts and alerts, but we also expect it to be responsible for complex life cycles around fetching and providing our server side and asynchronous data to our users.
So today, I'm here to tell you that despite the fleeting convenience global state gives us when working with server side data, I think we've made a really big mistake by placing it there. We've tricked ourselves and our code into thinking that all state is created equal, when I think our asynchronous data and global state could not be more different, especially when it comes to where they're stored, the speed at which we access them, and how we access and update them, and ultimately who can make changes to them.
To make all this easier to understand, I want to stop using the term global state and instead call these two different types of state client state and server state. Client state is relatively simple and should be familiar to most developers. It's temporary and local, and it's generally not persisted between sessions. It's accessed with synchronous APIs that don't have any latency, and most of it is owned by our client's application instance. So for all those reasons, we can pretty much rely on our client state always being up to date at any given time in our application.
Server state, however, is pretty different. Server state is persisted remotely, so the location source of truth for our server state is potentially unknown, or at least outside of our control. It's asynchronous, so we have to access it with asynchronous APIs, and it also has implied shared ownership, which means that it's not just owned by our client. It can be read and manipulated by both the server and any other potential clients that interact with it. Because of all these things, very few guarantees can actually be made around our server state always being up to date in our apps, and instead we usually end up relying on just snapshots of our async data.
Comments