Skip to content

createStore

Creates a store with an initial state and actions that can modify the state.

const store = createStore(config);
  • config - The configuration for the store.

The created store with state management methods.

  • get - Returns the current state of the store.
  • set - Sets the state of the store. If the new state is the current state itself (e.g. set((state) => state)), subscribers and onChange are not notified.
  • reset - Resets the state of the store to its initial value.
  • initialState - The initial state of the store.
  • actions - Actions that can modify the state of the store (if provided).
  • subscribe - Subscribes to changes in the state of the store. Returns an unsubscribe function.

The config object can contain the following properties:

Setup

  • initialState - The initial state of the store.
  • actions - A function that defines actions that can modify the state.

Lifecycle hooks

  • onLoad? - Invoked when the store is created.
  • onAttach? - Invoked when the store is subscribed to.
  • onDetach? - Invoked when the store is unsubscribed from.
  • onChange? - Invoked whenever the state changes.

Each hook receives a context object with:

  • get - Returns the current state of the store.
  • set - Sets the state of the store.
  • reset - Resets the state of the store to its initial value.
  • initialState - The initial state of the store.

Persistence

  • persist? - Whether to persist the state of the store.
  • key? - The unique key used to identify this store in storage. Required if persist is true.
  • storage? - The storage to use for persisting the state. Defaults to local storage if available. The state is synchronized with the storage when the window gains focus, and when another tab changes local or session storage.
  • syncWithStorageOn? - When to initially synchronize the store’s state with the storage. Defaults to “load”. Set to “attach” when using SSR to avoid hydration errors. See Persisting state with SSR.
  • serializer? - The serializer to use for storing the state. Defaults to JSON.
  • onStorageError? - Invoked with the error when the storage or the serializer throws, or with a StorageUnavailableError when no storage is available. The failed read or write is skipped and the state is left unchanged. Storage errors are not logged, so use this to surface them. A missing storage provider is also reported during SSR, where it can be safely ignored.
import { createStore } from "dharma-core";
const store = createStore({
initialState: { count: 0 },
actions: ({ set }) => ({
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}),
});
import { createStore } from "dharma-core";
import { State } from "./types";
const initialState: State = { data: null, loading: true, error: null };
const store = createStore({
initialState,
onAttach: async ({ set }) => {
try {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
set({ data, loading: false });
} catch (error) {
set({ error, loading: false });
}
},
onDetach: ({ reset }) => reset(),
});
import { createStore } from "dharma-core";
const store = createStore({
persist: true,
key: "count",
initialState: { count: 0 },
actions: ({ set }) => ({
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}),
});

By default, a persisted store reads from storage as soon as it is created. When the page is rendered on the server, the server has no access to the client’s storage and renders with the initial state, while the client renders with the persisted state. The two renders differ, which causes a hydration mismatch.

Setting syncWithStorageOn to "attach" delays the read until the store is first subscribed to. With useStore that happens after hydration, so the first client render matches the server, and the persisted state is applied right after as a regular update.

import { createStore } from "dharma-core";
const store = createStore({
persist: true,
key: "count",
syncWithStorageOn: "attach",
initialState: { count: 0 },
onStorageError: (error) => {
// There's no storage on the server, so nothing to report
if (typeof window === "undefined") return;
reportError(error);
},
});
import { createStore } from "dharma-core";
import superjson from "superjson";
const store = createStore({
persist: true,
key: "count",
storage: sessionStorage,
serializer: superjson,
initialState: { count: 0 },
actions: ({ set }) => ({
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}),
});
import { createStore } from "dharma-core";
const store = createStore({
persist: true,
key: "count",
initialState: { count: 0 },
onStorageError: (error) => reportError(error),
});