Перейти к содержимому
GitHubXDiscord

@triggery/zustand

Читай Zustand-стор из условия Triggery. Pull-only — селектор вызывается в момент срабатывания, а не на каждое обновление стора, поэтому хост-компонент никогда не ререндерится из-за этого хука.

npm bundle

pnpm add @triggery/core @triggery/react @triggery/zustand zustand

Peer-зависимости: react >= 18.0.0, zustand ^4 || ^5.

ЭкспортНазначение
useZustandCondition(trigger, name, store, selector)Регистрирует условие, читающее Zustand. Работает и со сторами на create (хук), и на createStore (vanilla).
import { create } from 'zustand';
import { createTrigger } from '@triggery/core';
import { useZustandCondition } from '@triggery/zustand';

type Settings = { sound: boolean; notifications: boolean };

const useSettings = create<Settings>(() => ({
  sound: true,
  notifications: true,
}));

const messageTrigger = createTrigger<{
  events: { 'new-message': { text: string } };
  conditions: { settings: Settings };
  actions: { showToast: { body: string } };
}>({
  id: 'message-received',
  events: ['new-message'],
  required: ['settings'],
  handler({ event, conditions, actions }) {
    if (!conditions.settings.notifications) return;
    actions.showToast?.({ body: event.payload.text });
  },
});

function SettingsBridge() {
  useZustandCondition(messageTrigger, 'settings', useSettings, (s) => s);
  return null;
}

Рантайм pull-only: selector(store.getState()) вызывается только при срабатывании триггера, а не при изменении стора. То есть:

  1. Ничего в React-дереве не ререндерится из-за этого хука. Если компоненту нужен тот же срез — рядом вызови собственный useStore(store, selector) Zustand.
  2. Триггер всегда видит актуальное состояние в момент срабатывания — без подписок и без риска устаревшего снимка.
useZustandCondition<T, S, K>(
  trigger: Trigger<S>,
  name: K,
  store: { getState(): T },
  selector: (state: T) => ConditionMap<S>[K],
): void