Say Goodbye to Redux Boilerplate: Effortless React State Management with Zustand

Development tutorial - IT technology blog
Development tutorial - IT technology blog

Zustand: Running Light Instead of Lifting Redux Weights

Have you ever felt “exhausted” writing dozens of lines of boilerplate just to update a username in Redux? If so, Zustand is your lifesaver. With a minimalist philosophy, this library weighs in at just 1.1KB. You don’t need a Provider to wrap your app, nor the mess of actions.js or reducers.js.

Install in a flash:

npm install zustand
# or
yarn add zustand

Let’s try creating a Counter store. You’ll see the difference immediately:

import { create } from 'zustand'

const useCounterStore = create((set) => ({
  count: 0,
  inc: () => set((state) => ({ count: state.count + 1 })),
  dec: () => set((state) => ({ count: state.count - 1 })),
}))

function Counter() {
  const { count, inc, dec } = useCounterStore()
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={inc}>Increase</button>
      <button onClick={dec}>Decrease</button>
    </div>
  )
}

The biggest plus? You just import the hook and use it directly. No messy <Provider> configuration in the root file.

Why Choose Zustand for Real-World Projects?

In a complex Dashboard project I worked on, using Context API caused performance bottlenecks. Every time a user typed into an input, dozens of charts below would re-render unnecessarily. After switching to Zustand, UI responsiveness increased by about 30% thanks to its smart rendering mechanism.

Zustand fundamentally solves 3 major issues:

  • Render Control: Only components that actually use the changed data will re-render.
  • Modern API: Fully leverages the power of React Hooks, making it extremely developer-friendly.
  • Flexible Access: You can retrieve state directly in API configuration files or utilities without needing a hook.

Key Features in Production

1. Surprisingly Simple Async Action Handling

Forget middlewares like Redux-Thunk. With Zustand, you simply use async/await right inside the store like a normal JavaScript function.

const useUserStore = create((set) => ({
  users: [],
  loading: false,
  fetchUsers: async () => {
    set({ loading: true })
    try {
      const res = await fetch('https://api.example.com/users')
      const data = await res.json()
      set({ users: data, loading: false })
    } catch (error) {
      set({ loading: false })
      console.error("Data loading error:", error)
    }
  },
}))

2. Persist Middleware – Automatic State Saving

Saving a shopping cart or theme to localStorage usually involves quite a bit of logic code. Zustand handles this with just a single wrapper function.

import { persist } from 'zustand/middleware'

const useSettingsStore = create(
  persist(
    (set) => ({
      theme: 'dark',
      toggleTheme: () => set((s) => ({ theme: s.theme === 'dark' ? 'light' : 'dark' })),
    }),
    { name: 'user-preferences' }
  )
)

Performance Optimization: Don’t Take the Whole “Store”

Many beginners make the mistake of const state = useStore(). This causes the component to re-render whenever any value in the store changes. Use Selectors to optimize:

// Only re-renders when count changes
const count = useCounterStore((state) => state.count)
const inc = useCounterStore((state) => state.inc)

This approach makes your application smoother, especially as the store grows larger.

Best Practices for Organizing Stores as Projects Grow

Implementing the Slices Pattern

Don’t cram all logic into a single file. Break the store down into separate “Slices” (e.g., AuthSlice, CartSlice) and then combine them. This makes the code more readable, maintainable, and easier to unit test.

Using Redux DevTools

Zustand integrates perfectly with Redux DevTools. You can still debug and view state change history just like in Redux, but with a much simpler setup.

Knowing When Not to Use a Store

Don’t overdo it. If a state only serves a single component (like the open/close state of a single modal), React’s useState is still the best choice. Only move data to the Store if it needs to be shared across multiple screens or requires long-term persistence.

Final Thoughts

Zustand isn’t just a library; it’s a practical state management mindset. It prioritizes developer speed and real-world performance over tedious conventions. If you’re starting a new React project, give Zustand a try. You certainly won’t regret it.

Happy coding!

Share: