TGViewer
Effector news Effector news @effector_news · 721 subscribers
Post #454 713

Forwarded from Elijah

Когда опенсорс это часть работы

Не так давно наша кодовая база на effector на рабочем проекте стала расти с бОльшей скоростью и, конечно, сильно влиять на легаси код.
Таким образом в огромных компонентах где смешаны бизнес-логика, ui-стейт, выполнение сайд-эффектов, преобразования данных, мемоизация итп, и туда стал проникать useUnit из effector.

useUnit - хук (в случае реакта), который связывает модель со вьюшкой. Если передан стор, то он подписывает компонент на этот стор и обновляет компонент, если стор изменился. Если переданы события или эффекты, то useUnit гарантированно вызовет это событие/эффект в нужной области (scope).

useUnit умеет "батчить" апдейты - если компонент подписан на несколько сторов/событий, то он дождется всех изменений и применит из разом, но только в том случае, если используется один useUnit.

const Component = () => {
const [user, products] = useUnit([$userStore, $productsStore])
}


Если используется несколько useUnit, то магии не случится, и каждое обновление будет вызывать обновление (ререндер) компонента.

const Component = () => {
const [products] = useUnit([$productsStore])
const [user] = useUnit([$userStore])
}


Очевидно – лучше меньше ререндеров, чем больше :)

Но как нам контроллировать количество вызовов этого самого useUnit? Особенно в большой кодовой базе в больших компонентах?

Вариант А – руками.
Ходить по всей кодовой базе, менять самостоятельно вызовы, бить по рукам разработчиков, которые по каким-то причинам не соблюдают такое простое правило.

Вариант Б – заиметь статический анализатор, который укажет на проблему и попробует пофиксить её автоматически.
По этому пути я и пошел - написал правило для eslint-плагина effector'a, которое парсит вызовы useUnit и мержит их, если возможно, или подсвечивает warning с ошибкой, которая сообщает, что лучше так не делать.

Хорошо, множественные useUnit устранили, но что если:
- Мы использовали в компоненте какой-то store, но теперь он нам не нужен. Мы его удалили по месту использования, но забыли удалить из useUnit

const Component = () => {
// Используем $user, но не используем $products
const [user] = useUnit([$user, $products]);

return <UserCard id={user.id} />
}


В таком случае подписка сохранится - если $products поменяется, то компонент тоже обновится. Неприятно.

Для этого кейса тоже можно написать ESLint-правило!
Парсим вызов useUnit (или его алиасов, если используете), смотрим на то, что было деструктурировано и сравниваем с аргументами, которые передали.
Если аргумент есть, а деструктурированного вызова нет - сообщаем об этом пользователю.

https://github.com/effector/eslint-plugin/pull/175
GitHub feat(use-unit-destructuring): add new rule for destructured units by Olovyannikov · Pull Request #175 · effector/eslint-plugin Problem: implicit subscriptions when forgot remove unused subscriptions inside react components e.g.: const { setValue } = useUnit({ value: $store, // not used, but create unnecessary re-render ...
  • 🔥 26
More from @effector_news
  1. Sep 11, 2026effector-vue 23.2.0 • Исправлена работа вложенной реактивности в useVModel и useGate в vue…
  2. Jul 20, 2026Post #463
  3. Jun 25, 2026@effector/reflect 10.1.0 ✨ Новая фича: mapProps const Hello = reflect({ view: Greeting, bi…
  4. Jun 16, 2026effector-eslint-plugin v0.19.0 ✨ Новое правило: enforce-exhaustive-useUnit-destructuring –…
  5. Jun 11, 2026Коммунити, принес вам потрогать очередную дата-фетчилку для эффектора. Паритет с farfetche…
  6. Jun 6, 2026Мы с Эдвардом залетели на стрим, рассказываем про произошедшую историю https://t.me/holyjs…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →