@triggery/solid
Биндинги SolidJS для Triggery. Та же форма хуков, что в @triggery/react и @triggery/vue, нативно работают с сигналами Solid и жизненным циклом onCleanup. Без рантайм-зависимостей — тонкая прослойка над жизненным циклом поверх @triggery/core.
Установка
Заголовок раздела «Установка»pnpm add @triggery/core @triggery/solid solid-js npm install @triggery/core @triggery/solid solid-js yarn add @triggery/core @triggery/solid solid-js bun add @triggery/core @triggery/solid solid-js Peer-зависимости: solid-js >= 1.8.0.
Что внутри
Заголовок раздела «Что внутри»| Экспорт | Назначение |
|---|---|
useEvent | Типизированный эмиттер событий со стабильной идентичностью на протяжении жизни компонента. |
useCondition | Регистрирует pull-only геттер условия. Естественно читает сигналы. |
useAction | Регистрирует обработчик действия. Автоочистка через onCleanup. |
useInlineTrigger | Одноразовые триггеры внутри компонента. |
<TriggerRuntimeProvider> | Внедрить кастомный рантайм через context API Solid. |
<TriggerScope> | Ограничить регистрации условий/действий поддеревом-фичей. |
Быстрый старт
Заголовок раздела «Быстрый старт»Три небольших файла. Триггер читается как спецификация, компоненты знают только о своём порту.
1. Опиши триггер
Заголовок раздела «1. Опиши триггер»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.notifications) return;
actions.showToast?.({
title: event.payload.author,
body: event.payload.text,
});
},
});2. Оберни дерево
Заголовок раздела «2. Оберни дерево»import { createRuntime } from '@triggery/core';
import { TriggerRuntimeProvider } from '@triggery/solid';
import { render } from 'solid-js/web';
import { App } from './App';
const runtime = createRuntime();
render(
() => (
<TriggerRuntimeProvider runtime={runtime}>
<App />
</TriggerRuntimeProvider>
),
document.getElementById('root')!,
);3. Подключи компоненты
Заголовок раздела «3. Подключи компоненты»import { createSignal, type Component } from 'solid-js';
import { useAction, useCondition, useEvent } from '@triggery/solid';
import { messageTrigger } from './triggers/message.trigger';
const SettingsProvider: Component = () => {
const [settings] = createSignal({ sound: true, notifications: true });
useCondition(messageTrigger, 'settings', () => settings());
return null;
};
const Chat: Component = () => {
const fire = useEvent(messageTrigger, 'new-message');
return (
<button onClick={() => fire({ text: 'hi', author: 'Alice' })}>
send
</button>
);
};
const Toast: Component = () => {
useAction(messageTrigger, 'showToast', ({ title, body }) =>
console.log(`[${title}] ${body}`),
);
return null;
};
export const App: Component = () => (
<>
<SettingsProvider />
<Chat />
<Toast />
</>
);Нажми на кнопку — Toast залогирует. Переключи settings.notifications в false — тишина.
Чем интеграция с Solid отличается от React
Заголовок раздела «Чем интеграция с Solid отличается от React»Компоненты Solid выполняют свой setup один раз. Никаких useCallback, массивов зависимостей и танцев с ref — просто замыкай то, что нужно. Геттеры условий, читающие сигналы, автоматически видят актуальное значение в момент срабатывания, потому что сигналы Solid — это чистые функции.
// Сравни с React: ни массива deps, ни useCallback, ни мемоизации.
useCondition(trigger, 'settings', () => settings());Очистка
Заголовок раздела «Очистка»Все composables автоматически очищаются через onCleanup — они работают и внутри setup’а компонента, и внутри отдельных createRoot()-скоупов. Никаких ручных disposer’ов.