Що таке "effect" в Effector?
У Effector effect - це реактивна одиниця для роботи з асинхронними діями (запити, таймери, операції з API тощо).
Якщо event - це «щось сталося», а store - «поточний стан»,
то effect - це "щось виконується" (зазвичай з побічною дією).
1. Що таке effect
Effect - це функція, обгортка над асинхронною логікою, яка автоматично керує станами:
pending,done,fail,finally.
Effector робить ефекти реактивними: вони можуть запускатися з подій, оновлювати стори, тригерити нові події і навіть викликати інші ефекти.
2. Приклад базового ефекту
import { createEffect } from 'effector'
const fetchUserFx = createEffect(async (id: number) => {
const res = await fetch(`/api/users/${id}`)
if (!res.ok) throw new Error('Помилка завантаження')
return res.json()
})
// Виклик ефекту
fetchUserFx(1)Тут:
createEffect()створює реактивний ефект.- Всередині - звичайна асинхронна функція.
- Effector сам відстежує, коли ефект:
- запущений ->
pending = true, - завершився ->
done, - впав з помилкою ->
fail.
- запущений ->
3. Автоматичні події ефекту
Кожен effect всередині Effector створює 4 вбудовані події:
| Подія | Коли викликається | Корисно для |
|---|---|---|
.pending | коли ефект виконується | показати "Loading…" |
.done | коли ефект завершений успішно | оновити дані |
.fail | коли сталася помилка | показати помилку |
.finally | коли ефект завершився (будь-яким результатом) | очистити індикатори, логіку завершення |
Приклад:
fetchUserFx.done.watch(({ params, result }) => {
console.log('Завантажили користувача', result)
})
fetchUserFx.fail.watch(({ error }) => {
console.error('Помилка:', error)
})4. Керування станом ефекту
Кожен effect - це не просто функція, а реактивний вузол.
У нього є store pending, який можна використовувати в UI:
import { useUnit } from 'effector-react'
function UserLoader() {
const [pending, loadUser] = useUnit([fetchUserFx.pending, fetchUserFx])
return (
<button onClick={() => loadUser(1)} disabled={pending}>
{pending ? 'Завантаження...' : 'Завантажити користувача'}
</button>
)
}Effector сам синхронізує значення pending - без ручного setState.
5. Зв'язок подій і ефектів
Зазвичай ефект запускається через подію, а не напряму:
import { createEvent, sample } from 'effector'
const userRequested = createEvent<number>()
sample({
clock: userRequested,
target: fetchUserFx,
})Тепер userRequested(42) викличе fetchUserFx(42).
6. Обробка результату через store
Після виконання ефекту дані можна зберегти в store:
import { createStore } from 'effector'
const $user = createStore(null)
.on(fetchUserFx.doneData, (_, user) => user)
.reset(fetchUserFx.fail)
$user.watch(console.log).doneData - це шорткат для effect.done.map(({ result }) => result).
7. Реактивний ланцюжок "event → effect → store → UI"
[event: userRequested] → [effect: fetchUserFx] → [store: $user] → [UI]Це класичний dataflow Effector: користувач ініціює подію -> ефект виконує запит -> результат реактивно оновлює стор -> UI оновлюється автоматично.
8. Відмінність від event і store
| event | effect | store | |
|---|---|---|---|
| Призначення | Повідомити, що щось сталося | Виконати асинхронну або побічну операцію | Зберігати й оновлювати дані |
| Повертає значення | Ні | Проміс | Дані (через .getState()) |
| Може змінювати state | Лише через зв'язку зі store | Лише через .doneData/.failData | Так |
| Реактивність | Так | Так | Так |
9. Приклад повного сценарію
import { createEvent, createEffect, createStore, sample } from 'effector'
// 1. подія від UI
const userRequested = createEvent<number>()
// 2. асинхронний ефект
const fetchUserFx = createEffect(async (id: number) => {
const res = await fetch(`/api/users/${id}`)
return res.json()
})
// 3. store для даних
const $user = createStore(null).on(fetchUserFx.doneData, (_, user) => user)
// 4. пов'язуємо подію з ефектом
sample({
clock: userRequested,
target: fetchUserFx,
})
// 5. слухаємо результат
$user.watch(console.log)
// виклик
userRequested(10)Підсумок
Effect в Effector - це реактивна асинхронна операція. Він:
- виконує побічні дії (запити, таймери, API),
- керує станом завантаження і помилок,
- пов'язується з іншими сутностями (events, stores),
- і ідеально інтегрується з реактивним потоком даних.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.