Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Managing State with Zustand: A Lightweight Alternative to Redux

Tech May 15 1

Zustand combiens the simplicity of React hooks with the state management capabilities of Redux. The create() function returns an object that serves as both a hook and a store, eliminating the need for separate providers and reducing boilerplate significantly.

Architecture Overview

┌─────────────────────────────┐
│    create() Return Value    │
│  (Both Hook and Store)      │
└──────────────┬──────────────┘
┌─────────────┐ ┌─────────────┐
│  React Hook │ │ Store Object│
│ useStore()  │ │getState()   │
│ (in components)│ │setState() │
│ subscribes │ │subscribe() │
└─────────────┘ └─────────────┘

Redux Implementation

Redux requires multiple imports and a structured approach with reducers, actions, and a Provider wrapper:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';

const operationMap = {
  INCREMENT: (s) => ({ count: s.count + 1 }),
  DECREMENT: (s) => ({ count: s.count - 1 }),
};

function counterReducer(state = { count: 0 }, action) {
  const handler = operationMap[action.type];
  return handler ? handler(state) : state;
}

const store = createStore(counterReducer);

function Counter() {
  const count = useSelector((s) => s.count);
  const dispatch = useDispatch();

  return (
    <div>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
      <span>{count}</span>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <Counter />
  </Provider>
);

Custom Hook Approach

React hooks provide local state management but lack shared state across components:

import React, { useState } from 'react';

function useCounter() {
  const [count, setCount] = useState(0);

  const increase = () => setCount((c) => c + 1);
  const decrease = () => setCount((c) => c - 1);

  return { count, increase, decrease };
}

function Counter() {
  const { count, increase, decrease } = useCounter();

  return (
    <div>
      <button onClick={decrease}>-</button>
      <span>{count}</span>
      <button onClick={increase}>+</button>
    </div>
  );
}

export default Counter;

Zustand Implementation

Zustand provides a minimal API that cmobines the best of both approaches:

import { create } from 'zustand';

const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

function Counter() {
  const { count, increment, decrement } = useCounterStore();
  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  );
}

export default Counter;

Accessing State Inside and Outside Components

// Inside components - uses hook (auto-subscribes and triggers re-renders)
const count = useCounterStore((state) => state.count);

// Outside components - uses getState() (no re-renders)
const count = useCounterStore.getState().count;

Full Example with External State Access

import React from 'react';
import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((s) => ({ count: s.count + 1 })),
  reset: () => set({ count: 0 }),
}));

function Counter() {
  const count = useStore((s) => s.count);
  const increment = useStore((s) => s.increment);
  const reset = useStore((s) => s.reset);

  return (
    <div>
      <div>Count: {count}</div>
      <button onClick={increment}>+</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

function externalIncrement() {
  const currentValue = useStore.getState().count;
  console.log('Current count:', currentValue);
  useStore.setState((s) => ({ count: s.count + 1 }));
}

export default function App() {
  return (
    <>
      <Counter />
      <button onClick={externalIncrement}>External +</button>
    </>
  );
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.