Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Cauen/79050a07f1cb330d7e7bc4717f30e50e to your computer and use it in GitHub Desktop.
Save Cauen/79050a07f1cb330d7e7bc4717f30e50e to your computer and use it in GitHub Desktop.
Expose Zustand Immer to Update Any Part of Store inside Components

Why?

In examples, we dont know how to use immer outside of the store implementation. Here's how to.

// store.ts
import { immer } from 'zustand/middleware/immer'
import { CreateOneShopOrderFromCheckoutInput } from '@/graphql/generated'
import { WritableDraft } from 'immer/dist/internal'

type State = {
  bears: number
} & CreateOneShopOrderFromCheckoutInput

interface Actions {
  increaseBear: (by: number) => void
  clearCheckout: () => void
  setState: (updater: (state: WritableDraft<State>) => void) => void
}

// ...

export const useCheckout = create<State & Actions>()(
  devtools(
    immer(
      persist((set) => ({
        ...initialState,
        increaseBear: (by) => set((state) => ({ bears: state.bears + by }), undefined, 'increase'),
        clearCheckout: () => set({ ...initialState }),
        setState: (e) => set(e) // immer exported
      }), {
        name: "checkout",
      })
    )
  )
)
// src/pages/checkout/form/shipping/city.tsx

const City: React.FC = () => {
  const { setValue, value } = useCheckout(
    (state) => ({
      setState: state.setState,
      value: state.Shipping.city,
    }),
    shallow
  );
  console.log("RENDERING CITY");

  return (
    <div>
      <Input
        label={"City"}
        value={value}
        onChange={(e) => {
          setState((state) => {
            // Using immer function inside component
            state.Shipping.city = e.target.value;
          });
        }}
      />
    </div>
  );
};

export default City;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment