Skip to content

A lightweight state management solution based on Zustand

License

Notifications You must be signed in to change notification settings

KamyarTaher/zust

Repository files navigation

Zust State Management

npm version License: MIT All Contributors

A lightweight and powerful state management library built on top of Zustand. Zust provides a simple API and a minimalistic approach for managing application state with ease.

Live Example

Check out this interactive example on CodeSandbox to see Zust in action:

Open CodeSandbox Example

Table of Contents

Installation

To install zust, use one of the following commands:

npm install zust

or

bun install zust

Usage

Here is a basic example of how to use Zust:

import { createStore } from 'zust';

// Define the initial state
const initialState = {
  user: { name: 'John', age: 30 },
  settings: { theme: 'light' as "light" | "dark" },
};

// Create the store
const { useSelectors, setDeep } = createStore(initialState);

function ExampleComponent() {
  // Select state values
  const { name, theme } = useSelectors('user.name', 'settings.theme');

  // Update state values
  const updateName = () => setDeep('user.name', 'Jane');
  const toggleTheme = () => setDeep('settings.theme', (prev) => (prev === 'light' ? 'dark' : 'light'));

  return (
    <div>
      <p>User Name: {name}</p>
      <p>Theme: {theme}</p>
      <button onClick={updateName}>Update User Name</button>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}

Usage with Aliases

Aliases help avoid conflicts and clarify the usage of deeply nested properties. Use aliases by appending : to the path.

import { createStore } from 'zust';

const initialState = {
  user: {
    profile: { name: 'John', email: 'john@example.com' },
    profile2: { name: 'Albert', email: 'albert@example.com' },
  },
  settings: { theme: 'dark' },
};

const { useSelectors, setDeep } = createStore(initialState);

function ExampleComponent() {
  const { name, secondName, theme } = useSelectors(
    'user.profile.name:name',
    'user.profile2.name:secondName',
    'settings.theme'
  );

  const updateSecondName = () => setDeep('user.profile2.name', 'Jane');

  return (
    <div>
      <p>User Name: {name}</p>
      <p>Second User Name: {secondName}</p>
      <p>Theme: {theme}</p>
      <button onClick={updateSecondName}>Update Second User Name</button>
    </div>
  );
}

Central Store vs. Multiple Stores

You can create a single central store or multiple smaller stores, depending on your application's needs.

Single Central Store Example:

import { createStore } from 'zust';

const initialState = {
  user: { name: 'John', age: 30 },
  settings: { theme: 'light' },
};

const { useSelectors, setDeep } = createStore(initialState);

Multiple Smaller Stores Example:

import { createStore } from 'zust';

// User store
const userState = {
  name: 'John',
  age: 30,
};

const { useSelectors: useUserSelectors, setDeep: setUserDeep } = createStore(userState);

// Settings store
const settingsState = {
  theme: 'light',
};

const { useSelectors: useSettingsSelectors, setDeep: setSettingsDeep } = createStore(settingsState);

Persistence

Zust allows you to persist parts of your state using localStorage. You can choose to persist entire branches or specific paths.

import { createStore, createPersistConfig } from 'zust';

const initialState = {
  user: { name: 'John', age: 30 },
  settings: { theme: 'light', language: 'en' },
};

// Create the store with persistence
const { useSelectors, setDeep } = createStore(initialState, {
  persist: createPersistConfig('user', 'settings.theme'),
});

To persist the entire store, set persist to true:

const { useSelectors, setDeep } = createStore(initialState, {
  persist: true,
});

API Reference

createStore

Creates a Zust store with the provided initial state and options.

Parameters:

  • initialState: The initial state of the store.
  • options: (optional): Configuration options.

Returns:

An object containing:

  • useStore: The Zust store hook.
  • useSelectors: A hook to select state values.
  • setDeep: A function to update state values.
  • subscribe: A function to subscribe to state changes.

createPersistConfig

Creates a configuration object for state persistence.

Parameters:

  • ...paths: State paths to persist.

Returns:

A configuration object for persistence.

loggingMiddleware

A middleware function for logging state changes.

Usage:

const options = {
  middleware: [loggingMiddleware],
};

const { useSelectors, setDeep } = createStore(initialState, options);

devToolsPlugin

Integrates the store with Redux DevTools for state debugging.

Usage:

import { createStore, devToolsPlugin } from 'zust';

const initialState = { /* ... */ };

const { useStore } = createStore(initialState);

devToolsPlugin(useStore, 'MyZustStore', initialState);

Options

StoreOptions<T>

  • persist?: boolean | PersistConfig<T>: : Enable or configure state persistence.

  • prefix?: string: Prefix for the localStorage key.

  • logging?: boolean: Enable console logging of state changes.

  • middleware?: Middleware<T>[]: Array of middleware functions.

  • computedValues?: { [key: string]: (state: T) => any }: Define computed values.

  • plugins?: Plugin<T>[]: Array of plugins to enhance store behavior.

Tests

Zust includes tests to verify its functionality:

  • Integration Tests: Ensure hooks and state updates work correctly.
  • Unit Tests: Test store creation, state updates, and middleware.

Contributions and pull requests for additional tests are welcome.

License

MIT License. See the LICENSE file for details.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Kamyar Taher
Kamyar Taher

🚇 ⚠️ 💻

This project follows the all-contributors specification. Contributions of any kind welcome!

About

A lightweight state management solution based on Zustand

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published