State is at the core of, well, everything.
I came to this realization more than once while working on all kinds of projects: frontend, backend, local-first, and more.
Let me walk you through why is that the case 🚶♂️➡️
What is an app really?
Most (all?) apps are data traders™. Every app works something like this:
- Data is stored somewhere (else), usually in a database
- The frontend is the system that takes and displays data (in a pretty-looking UI)
- The backend is the system that sits in between frontend and database, responsible for picking the data from the right source
From start (store data) to end (display data), it's all about data.
Coding problems are data problems
Let's make this even more concrete, by looking at a few examples:
- Caching: the data takes too much to load, so we store it somewhere closer
- Authentication: the data is sensitive, so we check that the user has the right data (e.g. token) to read other data
- Async/Promises: the data is not available right now, so we wait for it to be available
- Error handling: the data is missing, so we display something else
- State management: the data can change, so we keep track of it and the UI in sync as well
Read and write
Any software system is based on 2 core functionalities:
- Listen for events: the user clicking a button, a new API request received, the mouse moving
- React to these events and update some data
Data is the center of any software system: every app reads and displays the data, while at the same time it sends events to update the data
This is the essence of any software: update some data as new events are received.
As such, 2 key questions:
- How and from where do we read the data?
- How do we make sure that the data is up-to-date (after an update)?
Local-first: store data locally
Problems of data are greatly simplified when we store the data locally. That's one of the key selling points of local-first.
The client-server model is cursed by data problems:
- Async requests since data is somewhere else = possible request errors, delays, race conditions, need to handle promises,
Suspense
, etc. - Cached data to make the app faster = data out-of-sync, cache invalidation, etc.
- Authentication to make the app secure = risk of data leakage, stolen tokens, inaccessible personal data, etc.
That's a clear data problem caused by the choice of "where to store the data". Developers accept this complexity for the sake of "storing the data on a server" 😓
In local-first the data is (mainly) stored on the client:
- Data access can be synchronous = no promises, instant responses
- Cache is not even needed 💁🏼♂️
- Authentication is (mostly) not needed (since you access your own data after all)
Result: expect me to dig way more into the details of local-first in the next few months, it's the future 💯
State management is conducting and orchestra
When data can be so complex, state management requires a toolbox of features to handle all:
- Must work with async data and requests
- Must keep the current situation always in control (and in sync)
- Must consider possible errors and have a way to handle them
- Must have a way to make sure the data is valid
As I was writing my upcoming XState course, these problems became apparent.
XState is (probably) the only state management library that nailed all the requirements for a complete state orchestration system.
Keep the UI out of it!
On the extreme client-side of this all there is the UI. The UI must be kept out of this data-drama.
A UI component only knows about its own small world (what data do I get) and sends back events to request data changes.
That's way a state management library must be an all-in toolbox. As long as the state manager cannot handle some requests (looking at you useReducer
/Promise
), the UI needs to step in and deal with data.
Separate UI from state 💁🏼♂️ The UI is only responsible for 1️⃣ Render layout based on current state 2️⃣ Send events All the state management logic should be defined outside the component Key for maintainable state management 🔑
Conclusion: make sure your UI is pure (only layout/styles and sending events). If it's not, you have a state management problem. Try XState.
Quick update on the progress of my courses ℹ️
Working on the last lessons before opening my XState course for review. I updated the course structure recently to be more beginner-friendly (hopefully).
Updating my XState course structure 👨🎓 Target audience People used to useState/useReducer/Redux but interested in alternatives 💡 Strategy Start from useState and its problems, useReducer and its problems, then XState similarities and advantages
Meanwhile, if you didn't already, it's now the perfect time (again) to check out my Effect course 💡
This is one of the best intros to effect-ts. Shows the clear benefits in very concise examples. Very recommended to anybody who did not start with effect-ts yet! #typescript
@EffectTS_ Beginners Complete Getting Started course is out now 🚀 From zero to building complete apps with effect Type-safe, maintainable, testable apps, and it's just typescript 💯 Here is what you'll learn 👇🧵 typeonce.dev/course/effect-…
The XState course will be out in early September.
After that you'll see me dive deep (deep) into local-first. I will also publish some project-based courses using all the technologies I always talk about, combined 🪄
See you next 👋