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

@triggery/react

React-биндинги для Triggery. Хуки имеют ту же форму, что и в @triggery/solid и @triggery/vue. Без рантайм-зависимостей — тонкая прослойка над жизненным циклом поверх @triggery/core.

npm bundle

pnpm add @triggery/core @triggery/react

Peer-зависимости: react >= 18.0.0, react-dom >= 18.0.0.

ЭкспортНазначение
useEventТипизированный эмиттер событий со стабильной идентичностью.
useConditionРегистрирует pull-only геттер условия.
useActionРегистрирует обработчик действия.
useInlineTriggerОдноразовые триггеры внутри компонента.
useInspect / useInspectHistoryСнимок последнего запуска / история из кольцевого буфера.
createNamedHooksПолучить useNewMessageEvent, useUserCondition, … из триггера.
<TriggerRuntimeProvider>Внедрить кастомный рантайм в поддерево.
<TriggerScope>Ограничить регистрации условий/действий поддеревом-фичей.

Три небольших файла. Триггер читается как спецификация, компоненты знают только о своём порту.

src/triggers/message.trigger.ts
import { createTrigger } from '@triggery/core';

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

export const messageTrigger = createTrigger<{
  events: { 'new-message': { text: string; author: string } };
  conditions: { settings: Settings };
  actions: { showToast: { title: string; body: string } };
}>({
  id: 'message-received',
  events: ['new-message'],
  required: ['settings'],
  handler({ event, conditions, actions }) {
    if (!conditions.settings) return;
    if (!conditions.settings.notifications) return;
    actions.showToast?.({
      title: event.payload.author,
      body:  event.payload.text,
    });
  },
});
src/main.tsx
import { createRuntime } from '@triggery/core';
import { TriggerRuntimeProvider } from '@triggery/react';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';

const runtime = createRuntime();

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <TriggerRuntimeProvider runtime={runtime}>
      <App />
    </TriggerRuntimeProvider>
  </StrictMode>,
);
src/App.tsx
import { useAction, useCondition, useEvent } from '@triggery/react';
import { useState } from 'react';
import { messageTrigger } from './triggers/message.trigger';

function SettingsProvider() {
  const [settings] = useState({ sound: true, notifications: true });
  useCondition(messageTrigger, 'settings', () => settings, [settings]);
  return null;
}

function Chat() {
  const fire = useEvent(messageTrigger, 'new-message');
  return (
    <button type="button" onClick={() => fire({ text: 'hi', author: 'Alice' })}>
      send
    </button>
  );
}

function Toast() {
  useAction(messageTrigger, 'showToast', ({ title, body }) => console.log(`[${title}] ${body}`));
  return null;
}

export function App() {
  return (
    <>
      <SettingsProvider />
      <Chat />
      <Toast />
    </>
  );
}

Нажми на кнопку — Toast залогирует. Переключи settings.notifications в false — тишина.

На сервере хуки возвращают no-op’ы. Реальная подписка происходит в useEffect, поэтому гидрация не расходится. См. руководство по SSR и руководство по React Server Components.