zustand-computed-state
TypeScript icon, indicating that this package has built-in type declarations

0.1.8 • Public • Published

zustand-computed-state

npm package Build Status Downloads Issues

zustand-computed-state is a lightweight, TypeScript-friendly middleware for the state management system Zustand. It's a simple layer which adds a transformation function after any state change in your store.

Install

yarn add zustand-computed-state
npm install zustand-computed-state
pnpm add zustand-computed-state

Usage

The middleware layer takes in your store creation function and a compute function, which transforms your state into a computed state. It does not need to handle merging states.

import { computed, compute } from 'zustand-computed-state';

const useStore = create(
  computed((set, get) => ({
    count: 1,
    inc: () => set(state => ({ count: state.count + 1 })),
    dec: () => set(state => ({ count: state.count - 1 })),
    // get() function has access to computed states
    square: () => set(() => ({ count: get().countSq })),
    root: () => set(state => ({ count: Math.floor(Math.sqrt(state.count)) })),

    ...compute(get, state => ({
      countSq: state.count ** 2,
    })),
  }))
);

With types, the previous example would look like this:

import { computed } from 'zustand-computed-state';

type Store = {
  count: number;
  inc: () => void;
  dec: () => void;
  countSq: number;
};

const useStore = create<Store>()(
  computed((set, get) => ({
    count: 1,
    inc: () => set(state => ({ count: state.count + 1 })),
    dec: () => set(state => ({ count: state.count - 1 })),
    square: () => set(() => ({ count: get().countSq })),
    root: () => set(state => ({ count: Math.floor(Math.sqrt(state.count)) })),
    ...compute(get, state => ({
      countSq: state.count ** 2,
    })),
  }))
);

The store can then be used as normal in a React component or via the Zustand API.

function Counter() {
  const { count, countSq, inc, dec } = useStore();
  return (
    <div>
      <span>{count}</span>
      <br />
      <span>{countSq}</span>
      <br />
      <button onClick={inc}>+1</button>
      <button onClick={dec}>-1</button>
    </div>
  );
}

With Getters Pattern

Here's an example with the Getters Pattern

const useStore = create<Store>()(
  devtools(
    computed((set, get) =>
      compute<Store>({
        count: 1,
        inc: () => set(prev => ({ count: prev.count + 1 })),
        dec: () => set(state => ({ count: state.count - 1 })),
        get countSq() {
          return this.count ** 2;
        },
      })
    )
  )
);

With Middleware

Here's an example with the Immer middleware.

const useStore = create<Store>()(
  devtools(
    computed(
      immer((set, get) => ({
        count: 1,
        inc: () =>
          set(state => {
            // example with Immer middleware
            state.count += 1;
          }),
        dec: () => set(state => ({ count: state.count - 1 })),
        ...compute(get, state => ({
          countSq: state.count ** 2,
        })),
      }))
    )
  )
);

With Slice Pattern

Only difference is sending an ID to compute function to separate computed states for each slide.

- ...compute(get, state=>({xSq: state.x **2 }))
+ ...compute('x_slice', get, state=>({xSq: state.x **2 }))
type XSlice = {
  x: number;
  xSq: number;
  incX: () => void;
};

type YSlice = {
  y: number;
  ySq: number;
  incY: () => void;
};

type Store = YSlice & XSlice;

const createCountSlice: StateCreator<Store, [], [], YSlice> = (set, get) => ({
  y: 1,
  incY: () => set(state => ({ y: state.y + 1 })),
  ...compute('y_slice', get, state => ({
    ySq: state.y ** 2,
  })),
});

const createXySlice: StateCreator<Store, [], [], XSlice> = (set, get) => ({
  x: 1,
  incX: () => set(state => ({ x: state.x + 1 })),
  ...compute('x_slice', get, state => ({
    xSq: state.x ** 2,
  })),
});

const store = create<Store>()(
  computed((...a) => ({
    ...createCountSlice(...a),
    ...createXySlice(...a),
  }))
);

Readme

Keywords

none

Package Sidebar

Install

npm i zustand-computed-state

Weekly Downloads

3,326

Version

0.1.8

License

MIT

Unpacked Size

39.9 kB

Total Files

14

Last publish

Collaborators

  • yasintz