Исправление ошибок
Основные ошибки
store: undefined is used to skip updates. To allow undefined as a value provide explicit { skipVoid: false } option
Эта ошибка сообщает вам о том, что вы пытаетесь передать в ваш стор значение undefined
, что, возможно, является некорректным поведением.
Если вам действительно нужно передать в ваш стор значение undefined
, то вам надо вторым аргументом в createStore
передать объект со свойством skipVoid: false
.
const $store = createStore(0, { skipVoid: false,});
no handler used in [effect name]
Эта ошибка возникает при вызове эффекта без обработчика. Убедитесь, что вы передали обработчик в метод createEffect
при создании, или позже при использовании метода .use(handler)
.
serialize: One or more stores dont have sids, their values are omitted
До версии 23.3.0 эта ошибка также известна как: There is a store without sid in this scope, its value is omitted
.
Эта ошибка часто встречается при работе с SSR, она связана с тем, что у вашего стора отсутствует сид
(stable id), который необходим для корректной гидрации данных с сервера на клиент.
Чтобы исправить эту проблему вам нужно добавить этот сид
.
Сделать это вы можете несколькими способами:
-
Использовать babel или SWC плагин, который сделает все за вас
-
Или добавить
сид
в ручную, передав во второй аргументcreateStore
объект со свойствомsid
:const $store = createStore(0, {sid: "unique id",});
Более подробно про sid
, как это работает и зачем это нужно.
scopeBind: scope not found
Эта ошибка случается когда скоуп потерялся на каком-то из этапов выполнения и scopeBind
не может связать событие или эффект с нужным скоупом выполнения.
Эта ошибка могла быть вызвана:
- Вы используете режим работы ‘без скоупа’ и у вас их нет в приложении
- Ваши юниты были вызваны вне скоупа
Возможные решения:
-
Используйте
scopeBind
внутри эффектов:const event = createEvent();// ❌ - не вызывайте scopeBind внутри колбековconst effectFx = createEffect(() => {setTimeout(() => {scopeBind(event)();}, 1111);});// ✅ - используйте scopeBind внутри эффектаconst effectFx = createEffect(() => {const scopeEvent = scopeBind(event);setTimeout(() => {scopeEvent();}, 1111);}); -
Ваши юниты должны быть вызваны внутри скоупа:
- При работе с фреймворком используйте
useUnit
- Если у вас происходит вызов события или эффекта вне фреймворка, то используйте
allSettled
и передайте нужныйscope
в аргумент
- При работе с фреймворком используйте
Если того требует ваша реализация, а от ошибки нужно избавиться, то вы можете передать свойство safe:true
во второй аргумент метода.
const scopeEvent = scopeBind(event, { safe: true,});
call of derived event is not supported, use createEvent instead
Эта ошибка возникает, когда вы пытаетесь вызвать производное событие как функцию. Производные события создаются методами как .map()
, .filter()
, .filterMap()
, а также оператором sample
.
Чтобы исправить используйте событие созданное через createEvent
.
unit call from pure function is not supported, use operators like sample instead
Эта ошибка возникает, когда вы пытаетесь вызвать события или эффекты из чистых функций в Effector:
-
Вызов событий в методах событий
Когда вы пытаетесь вызвать одно событие внутри.map()
,.filter()
,.filterMap()
или.prepend()
другого события. -
Вызов событий в обработчиках сторов
При попытке вызвать событие в обработчике.on()
, внутри метода.map()
, или свойства конфигурацииupdateFilter()
стора. -
Вызов событий в функциях
sample
При вызове события в функцииfn
илиfilter
оператораsample
.
Как исправить: Вместо вызова событий в чистых функциях используйте декларативные операторы, например sample
.
Частые проблемы
sample.fn
не сужает тип, который приходит из sample.filter
Частая проблема с типизацией sample
происходит когда мы делаем проверку в filter
на что-то, но не получаем необходимый тип в fn
. Чтобы это исправить вы можете добавить предикаты типов или использовать effector-action
билблиотеку, которая поможет проще работать с условными типами:
import { sample } from "effector";
const messageSent = createEvent<Message>();const userText = createEvent<string>();
sample({ clock: messageSent, filter: (msg: Message): msg is UserMessage => msg.kind === "user", fn: (msg) => msg.text, target: userText,});
import { createAction } from "effector-action";
const userText = createEvent<string>();
const messageSent = createAction({ target: userText, fn: (userText, msg: Message) => { if (msg.kind === "user") { userText(msg.txt); } },});
Мое состояние не изменилось
Если ваше состояние не изменилось, то скорее всего вы работаете со скоупами и в какой-то момент активный скоуп потерялся и ваш юнит выполнился в глобальной области.
Типичные места, где это проявляется:
setTimeout
/setInterval
addEventListener
WebSocket
- прямой вызов промисов в эффектах
- сторонние библиотеки с асинхронными API или колбэки.
Решение: Привяжите ваше событие или эффект к текущему скоупу при помощи scopeBind
:
// ✅ все отработает корректно
const event = createEvent();
const effectFx = createEffect(() => { const scopedEvent = scopeBind(event);
setTimeout(() => { scopedEvent(); }, 1000);});
// ❌ событие вызовется в глобальном скоупе
const event = createEvent();
const effectFx = createEffect(() => { setTimeout(() => { event(); }, 1000);});
Использование юнитов без useUnit
Если вы используете события или эффекты во фреймворках без использования хука useUnit
, что может также повлиять на потерю скоупа.
Чтобы исправить это поведение передайте нужный юнит в useUnit
хук и используйте возвращаемое значение:
// ✅ использование хука
import { event } from "./model.js";import { useUnit } from "effector-react";
const Component = () => { const onEvent = useUnit(event);
return <button onClick={() => onEvent()}>click me</button>;};
// ❌ прямой вызов юнита
import { event } from "./model.js";
const Component = () => { return <button onClick={() => event()}>click me</button>;};
Не нашли ответ на свой вопрос ?
Если вы не нашли ответ на свой вопрос, то вы всегда можете задать сообществу:
Документация на английском языке - самая актуальная, поскольку её пишет и обновляет команда effector. Перевод документации на другие языки осуществляется сообществом по мере наличия сил и желания.
Помните, что переведенные статьи могут быть неактуальными, поэтому для получения наиболее точной и актуальной информации рекомендуем использовать оригинальную англоязычную версию документации.