State management is one of the most important parts of frontend development, As the web apps are getting more and more complex with time to provide the most optimal user experience, and to achieve this they are experimenting with different architectures to have a frictionless development experience.

The larger the application, the more complex the state management. As the team starts to grow it becomes harder to manage the state of the application, thus the states can be broken down into smaller chunks and can be limited to components or module level, or business logic.

The concept of the Micro-State management is derived from the concept of microservices, The idea is to slice a monolith frontend into smaller chunks that can be managed, developed, and deployed independently by smaller dev teams.

We will see how we can do the micro-state management with Zustand in React. Zustand is a tiny library created to provide a module state for React. It is based on the Immutable update model, in which states objects cannot be modified but always have to be newly created.

Using selectors we can optimize the render manually, it also comes with a straightforward, yet powerful state creator interface.

Understanding module state and immutable state.

Module state

In module state, stores are defined in modules and we export them, they work on the Singleton + Factory design pattern where all the boilerplate logic to create the store and update them will reside in a module (function) that can be exported and used.

The store will share the state wherever used, which means if the same state has been accessed in two different components and one component updates the state, the second component will also re-render.

We can create a store and use that as a hook within the functional component.

//store.js
import { create } from "zustand";
export const store = create(() => ({ count: 0 }));

Immutable state.

Zustand is based on the Immutable state model, in which you are not allowed to modify the state objects directly, if you want to update the state, you will have to create a new object, you can reuse the unmodified state objects. The benefit of the immutable state model is that you only need to check state object referential equality to know if there's any update; you don't have to check equality deeply.

Let's import the store and see the working of it with the following example.

// App.js
import { store } from "./store";

function App(){
  console.log(store.getState()); // {count: 0};
  return null;
}

store function exposes few methods like getState(), setState(), and subscribe().

getState() is used to get the state in the store and setState() is used to update the state in the store.

console.log(store.getState()); // ---> { count: 0 }

store.setState({ count: 1 });

console.log(store.getState()); // ---> { count: 1 }

The state objects are immutable, updating the state properties directly won't update the state and thus will not trigger the re-render.

const state1 = store.getState();

state1.count = 2; // invalid, won't work;

store.setState(state1);