Skip to content

zustandjs/zustand-injectors

Repository files navigation

zustand-injectors

CI npm size discord

A sweet way to lazy load slices

Install

npm i zustand zustand-injectors

Usage

Auto lazy load slices

// src/create-decrement-slice.ts
import type { StateCreator } from "zustand";

import type { CounterStore } from "./counter-store";

export const createDecrementSlice: StateCreator<
  CounterStore,
  [],
  [],
  { decrementCount: () => void }
> = (set) => ({
  decrementCount: () => {
    set((currentState) => ({ count: currentState.count - 1 }));
  },
});
// src/counter-store.ts
import { createStore } from "zustand";
import { injectors } from "zustand-injectors";

export type CounterState = { count: number };

export type CounterActions = {
  incrementCount: () => void;
  decrementCount: () => void;
};

export type CounterStore = CounterState & CounterActions;

export const counterStore = createStore<CounterStore>()(
  injectors(
    (set) => ({
      count: 0,
      incrementCount: () => {
        set((currentState) => ({ count: currentState.count + 1 }));
      },
      decrementCount: () => {},
    }),
    {
      "decrement-slice": () =>
        import("./create-decrement-slice").then(
          (mod) => mod.createDecrementSlice
        ),
    }
  )
);
// main.tsx
import { useLayoutEffect } from "react";
import { useStore } from "zustand";

const Component = () => {
  const { count, incrementCount, decrementCount } = useStore(counterStore);

  return null;
};

Manual lazy load slices

// src/create-decrement-slice.ts
import type { StateCreator } from "zustand";

import type { CounterStore } from "./counter-store";

export const createDecrementSlice: StateCreator<
  CounterStore,
  [],
  [],
  { decrementCount: () => void }
> = (set) => ({
  decrementCount: () => {
    set((currentState) => ({ count: currentState.count - 1 }));
  },
});
// src/counter-store.ts
import { useLayoutEffect } from "react";
import { createStore } from "zustand";
import { injectors } from "zustand-injectors";

export type CounterState = { count: number };

export type CounterActions = {
  incrementCount: () => void;
  decrementCount: () => void;
};

export type CounterStore = CounterState & CounterActions;

export const counterStore = createStore<CounterStore>()(
  injectors((set) => ({
    count: 0,
    incrementCount: () => {
      set((currentState) => ({ count: currentState.count + 1 }));
    },
    decrementCount: () => {},
  }))
);
// src/main.tsx
import { useLayoutEffect } from "react";
import { useStore } from "zustand";

const Component = () => {
  const { count, incrementCount, decrementCount } = useStore(counterStore);

  useLayoutEffect(() => {
    counterStore.injectAsyncSliceInitializer("decrement-slice", () =>
      import("./create-decrement-slice").then((mod) => mod.createDecrementSlice)
    );
  }, []);

  return null;
};