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

TriggerScope

Стабильный · с 0.1.0

Передаёт id скоупа потомкам. Вызовы useCondition и useAction внутри этого поддерева регистрируются со скоупом, и только триггеры, объявленные с таким же scope в createTrigger(...), их увидят. Рантайм, инспектор, планировщик и middleware остаются общими — TriggerScope это более лёгкое внутрирантаймовое разделение по сравнению с <TriggerRuntimeProvider>.

Используй его, когда один рантайм — это правильно, но нужно, чтобы две половины дерева регистрировали независимых провайдеров для одного и того же условия или действия.

import { TriggerScope } from '@triggery/react';
function TriggerScope(props: TriggerScopeProps): JSX.Element;

type TriggerScopeProps = {
  readonly id: string;
  readonly children: ReactNode;
};
ПропТипОбязательныйОписание
idstringдаId скоупа. Должен совпадать с полем scope триггера, чтобы связаться.
childrenReactNodeдаПоддерево, в котором регистрации помечаются id.
import { createTrigger } from '@triggery/core';
import { TriggerScope, useAction, useCondition, useEvent } from '@triggery/react';

const messageTrigger = createTrigger<{
  events: { 'new-message': { author: string; text: string } };
  conditions: { activeChannelId: string };
  actions: { showToast: { title: string } };
}>({
  id: 'chat:new-message',
  scope: 'chat',
  events: ['new-message'],
  required: ['activeChannelId'],
  handler({ event, conditions, actions }) {
    if (event.payload.author === conditions.activeChannelId) return;
    actions.showToast?.({ title: event.payload.author });
  },
});

function ChatA() {
  useCondition(messageTrigger, 'activeChannelId', () => 'a', []);
  useAction(messageTrigger, 'showToast', t => console.log('toast A', t.title));
  return null;
}
function ChatB() {
  useCondition(messageTrigger, 'activeChannelId', () => 'b', []);
  useAction(messageTrigger, 'showToast', t => console.log('toast B', t.title));
  return null;
}

function Page() {
  return (
    <>
      <TriggerScope id="chat">
        <ChatA />
      </TriggerScope>
      <TriggerScope id="chat">
        {/* Second scope — registrations from ChatB would override ChatA's
            but they're in a different boundary. Use distinct ids if you want
            truly independent buckets. */}
        <ChatB />
      </TriggerScope>
    </>
  );
}

Независимые скоупы для двух инстансов триггеров

Заголовок раздела «Независимые скоупы для двух инстансов триггеров»
import { createTrigger } from '@triggery/core';
import { TriggerScope, useCondition } from '@triggery/react';

const triggerLeft = createTrigger<{
  events: { ping: void };
  conditions: { value: number };
}>({ id: 'left', scope: 'left', events: ['ping'], required: ['value'], handler() {} });

const triggerRight = createTrigger<{
  events: { ping: void };
  conditions: { value: number };
}>({ id: 'right', scope: 'right', events: ['ping'], required: ['value'], handler() {} });

function Layout() {
  return (
    <>
      <TriggerScope id="left">
        <Provider t={triggerLeft} v={1} />
      </TriggerScope>
      <TriggerScope id="right">
        <Provider t={triggerRight} v={2} />
      </TriggerScope>
    </>
  );
}

function Provider({ t, v }: { t: ReturnType<typeof createTrigger>; v: number }) {
  useCondition(t, 'value', () => v, [v]);
  return null;
}

Внутренний id побеждает для всего, что внутри него:

import { TriggerScope } from '@triggery/react';

<TriggerScope id="outer">
  {/* registrations here tagged "outer" */}
  <TriggerScope id="inner">
    {/* registrations here tagged "inner" */}
  </TriggerScope>
</TriggerScope>