Структура модели
В дополнение к вышесказанному мы также рекомендуем разделять юниты модели на публичные и приватные.
Также бывает удобно выносить в отдельный модуль обработчики эвентов (редьюсеры), если они становятся слишком велики и ухудшают читаемость модели.
Таким образом, наша модель приобретает следующую структуру:
public.ts — внешние "публичные" юниты модели
private.ts — приватные юниты модели
reducers.ts — обработчики событий (опциональны)
init.ts — бизнес-логика, связывание сторов и эвентов, никогда не экспортирует
index.ts — точка входа, реэкспорт всех юнитов из public
Объявленные в public.ts
публичные юниты реэкспортируются во внешний мир в точке входа модели (index.ts
). Объявленные в private.ts
приватные юниты НИКОГДА не должны экспортироваться за пределы фичи. Эти юниты допускается импортить только в init.ts
этой же модели, или в представлениях этой же фичи.
Если определенное приватное событие или состояние требуется "отдать" во внешний мир, создайте второе публичное событие и свяжите их через forward
в init.ts
:
public.ts
:
export const publicEvent = domain.event<void>()
export const $publicState = domain.store<Item[]>()
private.ts
:
export const privateEvent = domain.event<void>()
export const $privateState = domain.store<Item[]>()
init.ts
:
import { forward } from 'effector'
import { publicEvent, $publicState } from './public.ts'
import { privateEvent, $privateState } from './private.ts'
forward({
from: publicEvent,
to: privateEvent,
})
forward({
from: $privateState,
to: $publicState,
})
Подобная практика в сочетании с разделением объявления и инициализации позволяет:
- Полностью избежать проблем с циклическими зависимостями между моделями.
- Явно и прозрачно выделить публичное API, через которое внешние модели могут изменять ее состояние.
Не создавайте пустые файлы только "ради структуры". Если в данной модели нет данного модуля, не делайте его.