Skip to content

Enjoy the performance gain of selectors without writing selectors in Zustand.

License

Notifications You must be signed in to change notification settings

Albert-Gao/auto-zustand-selectors-hook

Repository files navigation

auto-zustand-selectors-hook

Enjoy the performance gain of selectors without writing selectors!

Features

  • auto generate selectors for Zustand store (be it a value or a function)
  • Two styles available
  • Fully Typescript support (auto-completion for the generated selectors!)

Install

npm install --save auto-zustand-selectors-hook

Or with yarn:

yarn add auto-zustand-selectors-hook

Notice

The v2 supports Zustand v4, if you are using a Zustand v3, please install the v1 version

yarn add auto-zustand-selectors-hook@1.0.1

npm install --save auto-zustand-selectors-hook@1.0.1

Usage

Let's say you have a store like this

interface BearState {
  bears: number;
  increase: (by: number) => void;
}

const useStoreBase = create<BearState>((set) => ({
  bears: 0,
  increase: (by) => set((state) => ({ bears: state.bears + by })),
}));

There are two types of selectors you can generate, purely function signature difference, underneath, they are all selectors.

1. For function style ( createSelectorFunctions )

import { createSelectorFunctions } from 'auto-zustand-selectors-hook';
import { create } from 'zustand';

// wrap your store
const useStore = createSelectorFunctions(useStoreBase);

// use it like this!
// useStore.use.blah is a pre-generated selector, yeah!
const TestComponent = () => {
  const bears = useStore.use.bears();
  const increase = useStore.use.increase();

  return (
    <>
      <span>{bears}</span>

      <button
        onClick={() => {
          increase(1);
        }}
      >
        +
      </button>
    </>
  );
};

2. For hook style ( createSelectorHooks )

import { createSelectorHooks } from 'auto-zustand-selectors-hook';
import { create } from 'zustand';

// wrap your store
const useStore = createSelectorHooks(useStoreBase);

// use it like this!
// useStore.useBlah is a pre-generated selector, yeah!
const TestComponent = () => {
  const bears = useStore.useBears();
  const increase = useStore.useIncrease();

  return (
    <>
      <span>{bears}</span>

      <button
        onClick={() => {
          increase(1);
        }}
      >
        +
      </button>
    </>
  );
};

3. use with middlewares

You use the middleware for creating the base store, and ALWAYS use auto-zustand-selectors-hooks as a separate wrapper

import {
  createSelectorHooks,
  ZustandFuncSelectors,
  ZustandHookSelectors,
} from 'auto-zustand-selectors-hook';
import create from 'zustand';
import { persist } from 'zustand/middleware';

const useStoreBase = create<BearState>()(
  persist((set) => ({
    bears: 0,
    increase: (by) => set((state) => ({ bears: state.bears + by })),
  }))
);

// ❌ this will lost  the persist middleware type like useStore.persist
export const useStore = createSelectorHooks(useStoreBase);

// ✅ DO this if use createSelectorFunctions()
export const useStore = createSelectorFunctions(
  useStoreBase
) as typeof useStoreBase & ZustandFuncSelectors<BearState>;

// ✅ DO this if use createSelectorHooks()
export const useStore = createSelectorHooks(
  useStoreBase
) as typeof useStoreBase & ZustandHookSelectors<BearState>;

License

MIT © Albert Gao

Credits

It all starts from my feature request Thanks dai-shi for the initial implementation and ideas of API.

About

Enjoy the performance gain of selectors without writing selectors in Zustand.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published