Files
oranguru/llm/docs/zustandsyncstore.md
Hein 7244bd33fc refactor(advancedSearch): reorder exports and improve type definitions
refactor(types): reorganize SearchCondition and AdvancedSearchState interfaces
refactor(filterPresets): streamline useFilterPresets hook and localStorage handling
refactor(filtering): clean up ColumnFilterButton and ColumnFilterPopover components
refactor(loading): separate GriddyLoadingOverlay from GriddyLoadingSkeleton
refactor(searchHistory): enhance useSearchHistory hook with persistence
refactor(index): update exports for adapters and core components
refactor(rendering): improve EditableCell and TableCell components for clarity
refactor(rendering): enhance TableHeader and VirtualBody components for better readability
2026-02-15 19:54:33 +02:00

3.4 KiB

@warkypublic/zustandsyncstore v1.0.0

React library providing synchronized Zustand stores with prop-based state management and persistence support.

Peer Dependencies

  • react >= 19.0.0
  • zustand >= 5.0.0
  • use-sync-external-store >= 1.4.0

Runtime Dependencies

  • @warkypublic/artemis-kit

API

Single export: createSyncStore

import { createSyncStore } from '@warkypublic/zustandsyncstore';

createSyncStore<TState, TProps>(createState?, useValue?)

Parameters:

  • createState (optional): Zustand StateCreator<TState> function
  • useValue (optional): Custom hook receiving { useStore, useStoreApi } & TProps, returns additional state to merge

Returns: SyncStoreReturn<TState, TProps> containing:

  • Provider — React context provider component
  • useStore — Hook to access the store

Provider Props

Prop Type Description
children ReactNode Required
firstSyncProps string[] Props to sync only on first render
persist PersistOptions<Partial<TProps & TState>> Zustand persist config
waitForSync boolean Wait for sync before rendering children
fallback ReactNode Shown while waiting for sync
...TProps TProps Custom props synced to store state

useStore Hook

const state = useStore();                                    // entire state (TState & TProps)
const count = useStore(state => state.count);                // with selector
const count = useStore(state => state.count, (a, b) => a === b);  // with equality fn

Usage

Basic

interface MyState { count: number; increment: () => void; }
interface MyProps { initialCount: number; }

const { Provider, useStore } = createSyncStore<MyState, MyProps>(
  (set) => ({
    count: 0,
    increment: () => set((state) => ({ count: state.count + 1 })),
  })
);

function Counter() {
  const { count, increment } = useStore();
  return <button onClick={increment}>Count: {count}</button>;
}

function App() {
  return (
    <Provider initialCount={10}>
      <Counter />
    </Provider>
  );
}

With Custom Hook Logic

const { Provider, useStore } = createSyncStore<MyState, MyProps>(
  (set) => ({ count: 0, increment: () => set((s) => ({ count: s.count + 1 })) }),
  ({ useStore, useStoreApi, initialCount }) => {
    const currentCount = useStore(state => state.count);
    return { computedValue: initialCount * 2 };
  }
);

With Persistence

<Provider initialCount={10} persist={{ name: 'my-store', storage: localStorage }}>
  <Counter />
</Provider>

Selective Prop Syncing

<Provider initialCount={10} otherProp="value" firstSyncProps={['initialCount']}>
  <Counter />
</Provider>

Internal Types

type LocalUseStore<TState, TProps> = TState & TProps;

// Store state includes a $sync method for internal prop syncing
type InternalStoreState<TState, TProps> = TState & TProps & {
  $sync: (props: TProps) => void;
};

type SyncStoreReturn<TState, TProps> = {
  Provider: (props: { children: ReactNode } & {
    firstSyncProps?: string[];
    persist?: PersistOptions<Partial<TProps & TState>>;
    waitForSync?: boolean;
    fallback?: ReactNode;
  } & TProps) => React.ReactNode;
  useStore: {
    (): LocalUseStore<TState, TProps>;
    <U>(selector: (state: LocalUseStore<TState, TProps>) => U, equalityFn?: (a: U, b: U) => boolean): U;
  };
};