๐๐ป Introduction
In React applications we are dealing with state all of the time. Be it useState
hook or useReducer
hook, we always try to ensure our states are handled most efficiently. Redux and Redux toolkit are two libraries that help you manage state more globally like React's context API. But, the problem with using Redux and Redux toolkit is they have a more steep learning curve. So what is Zustand and how can it help us to manage state better than Redux or Redux toolkit?
๐ Redux vs. Zustand
Redux is powerful, but its power depends on its complexity. It requires setting up actions, reducers, and stores which can be overwhelming for developers. But Zustand takes a simple approach by letting you manage the state with a single hook. This simplicity makes Zustand more accessible, especially for smaller projects or developers new to state management.
Also, when working with Redux, it is notable that Redux enforces immutability. Although it is a good practice for predictable state changes, it requires a lot of code to achieve that. On the other hand, Zustand simplifies immutability by allowing the user to directly mutate state with its integration on useReducer
and useState
hooks.
In addition, Zustand takes advantage of React's context and hooks to optimize re-renders. This increases the performance of the application compared to how Redux uses too much boilerplate code to manage the state.
Furthermore, with the advent of React Concurrent Mode, Zustand is well-suited to work seamlessly with it. Since the Concurrent Mode is designed to improve the performance of the React applications, Zustand's lightweight nature fits well with it.
Although there is a vast community backing Redux, Zustand's community is growing steadily due to its simplicity and ease of use as well.
Therefore, learning Zustand in 2024 will be a great help to any developer who is going to learn state management with React.
๐ป Zustand
Now, let's look at how you can use Zustand to manage your states.
import React, {useState} fom 'react';
const CountComponent = ({count}) => {
function incrementCount(){
//how can we do this?
}
function decrementCount(){
//how can we do this?
}
return (
<>
<div onClick={decrementCount}>-</div>
<div>{count}</div>
<div onClick={incrementCount}>+</div>
</>
);
}
const App = () => {
const [count, setCount] = useState(0);
return (
<CountComponent count={count}/>
);
}
export default App;
In the above code, we have two components, App
and CountComponent
. We need to change the count
value when we click either + or -. But since the setCount
function is bound to App
component we cannot change it directly. Therefore, to overcome this issue, we need a global state management solution.
To do that, we need to first install the Zustand to our React project. We can do that by typing npm install zustand
or yarn add zustand
depending on what package manager you are using. After that, we can simply create a store to manage the state with Zustand.
// store.js
import {create} from 'zustand';
export const countStore = create((set)=>({
count: 0,
increment: () => set((state)=>({count: state.count + 1})),
decrement: () => set((state)=>({count: state.count - 1}))
}));
The set
function is used to set values in the Zustand store. After creating the store you can simply bind your components as shown below.
//app.js
import React, {useState} fom 'react';
import {countStore} from 'store';
const CountComponent = ({count}) => {
// get values from countStore
const incrementCount = countStore(state => state.increment);
const decrementCount = countStore(state => state.decrement);
return (
<>
<div onClick={decrementCount}>-</div>
<div>{count}</div>
<div onClick={incrementCount}>+</div>
</>
);
}
const App = () => {
// get count value from countStore
const count = countStore((state)=>state.count);
return (
<CountComponent count={count}/>
);
}
export default App;
You can see how easy was it to manage the state with Zustand. You just need to define a store with what may cause the changes and you can bind it to your components without worrying about the state immutability or reducers or dispatchers.
It is also important to note that you can use asynchronous functions with Zustand without worrying about middleware as well.