Zustand Slices Utility

0.4.0 · active · verified Tue Apr 21

zustand-slices is a utility library designed to introduce an opinionated, TypeScript-friendly slice pattern for Zustand, a minimalist global state management library. As of version 0.4.0, it provides `createSlice` and `withSlices` helpers to structure Zustand stores into modular, reusable "slices." This addresses the complexities often encountered when attempting to implement such patterns with strong TypeScript typing, particularly when following the official Zustand documentation's manual approach. The library is actively developed, with its primary maintainer frequently tweeting about updates and examples, suggesting a consistent, though not strictly scheduled, release cadence focusing on refinement and new features. Its key differentiator is its explicit support for type inference and clean separation of concerns within a Zustand store, leveraging immutable updates via Immer, which is a peer dependency.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define individual state slices using `createSlice`, combine them into a single Zustand store with `withSlices`, and consume both state and actions within a React component. It also highlights distinct reset actions for each slice to avoid naming conflicts.

import { create } from 'zustand';
import { createSlice, withSlices } from 'zustand-slices';

interface CountState {
  count: number;
  inc: () => void;
  resetCount: () => void;
}

interface TextState {
  text: string;
  updateText: (newText: string) => void;
  resetText: () => void;
}

const countSlice = createSlice<CountState>()({
  name: 'count',
  value: 0,
  actions: {
    inc: () => (prev) => prev + 1,
    resetCount: () => () => 0,
  },
});

const textSlice = createSlice<TextState>()({
  name: 'text',
  value: 'Hello',
  actions: {
    updateText: (newText: string) => () => newText,
    resetText: () => () => 'Hello',
  },
});

// Combine slices and create the store
const useStore = create(withSlices(countSlice, textSlice));

// Example component usage (requires React environment)
function MyComponent() {
  const count = useStore((state) => state.count);
  const text = useStore((state) => state.text);
  // Destructuring actions from getState() to ensure referential stability
  const { inc, updateText, resetCount, resetText } = useStore.getState(); 

  return (
    <>
      <p>
        Count: {count}
        <button type="button" onClick={inc}>
          +1
        </button>
      </p>
      <p>
        <input value={text} onChange={(e) => updateText(e.target.value)} />
      </p>
      <p>
        <button type="button" onClick={resetCount}>
          Reset Count
        </button>
        <button type="button" onClick={resetText}>
          Reset Text
        </button>
      </p>
    </>
  );
}

// To use MyComponent, render it within a React application.
// For example, in a simple setup:
// import React from 'react';
// import ReactDOM from 'react-dom/client';
// const root = ReactDOM.createRoot(document.getElementById('root'));
// root.render(<MyComponent />);

view raw JSON →