Troubleshooting Effector
Common Errors
store: undefined is used to skip updates. To allow undefined as a value provide explicit {Ā skipVoid:Ā falseĀ } option
This error indicates that you are trying to pass undefined
as a value to your store, which might not be the intended behavior.
If you really need to store undefined
, pass an object with {Ā skipVoid:Ā falseĀ }
as the second argument to createStore
:
const $store = createStore(0, { skipVoid: false,});
no handler used in [effect name]
This error occurs when calling an effect without a handler. Make sure you passed a handler to the createEffect
method during creation, or later when using the .use(handler)
method.
serialize: One or more stores dont have sids, their values are omitted
Before version 23.3.0, this error was also known as: There is a store without sid in this scope, its value is omitted
.
This error commonly occurs in SSR scenarios due to the absence of an sid
(stable id), which is required for proper hydration of store data from the server to the client.
To fix this, add an sid
to your store. You can do this in one of the following ways:
-
Manually specify an
sid
by providing an object with asid
property as the second argument tocreateStore
:const $store = createStore(0, {sid: "unique id",});
For more details, see Understanding sid
and its purpose.
scopeBind: scope not found
This error occurs when a scope is lost at some point in execution, preventing scopeBind
from associating an event or effect with the correct execution scope.
It may be caused by:
- Using a āscope-freeā mode where scopes are not present in your application.
- Calling units outside of a scope.
Possible Solutions:
-
Ensure
scopeBind
is used within effects:const event = createEvent();// ā - Do not call scopeBind inside callbacksconst effectFx = createEffect(() => {setTimeout(() => {scopeBind(event)();}, 1111);});// ā - Use scopeBind inside the effectconst effectFx = createEffect(() => {const scopeEvent = scopeBind(event);setTimeout(() => {scopeEvent();}, 1111);}); -
Ensure that your units are used inside a scope:
- When working with a framework, use
useUnit
. - If calling an event or effect outside a framework, use
allSettled
and provide the appropriatescope
as an argument.
- When working with a framework, use
If necessary, and you want to suppress the error, you can pass {Ā safe:Ā trueĀ }
as an option:
const scopeEvent = scopeBind(event, { safe: true,});
call of derived event is not supported, use createEvent instead
This error occurs when you try to call a derived event as a function. Derived events are created by methods like .map()
, .filter()
, .filterMap()
, as well as the sample
operator.
To fix this, use an event created via createEvent
.
unit call from pure function is not supported, use operators like sample instead
This error occurs when you try to call events or effects from pure functions in Effector:
-
Calling events in event methods
When you try to call one event inside another eventās.map()
,.filter()
,.filterMap()
, or.prepend()
methods. -
Calling events in store handlers
When attempting to call an event in a.on()
handler, inside the.map()
method, or in theupdateFilter()
configuration property of a store. -
Calling events in
sample
functions
When calling an event in thefn
orfilter
function of thesample
operator.
How to fix: Instead of calling events in pure functions, use declarative operators, for example, sample
.
Gotchas
sample.fn
does not narrow the type passed from sample.filter
A common type-related issue with sample
occurs when a check is performed inside filter
, but fn
does not receive the expected narrowed type.
My state did not change
If your state does not update as expected, you are likely working with scopes and, at some point, the active scope was lost. As a result, your unit executed in the global scope instead.
Find more details about this behavior here.
This issue often occurs when passing units (events or effects) into external function callbacks such as:
setTimeout
/setInterval
addEventListener
webSocket
, etc.
Solution:
Bind your event or effect to the current scope using scopeBind
:
const event = createEvent();
// ā - This will execute the event in the global scopeconst effectFx = createEffect(() => { setTimeout(() => { event(); }, 1000);});
// ā
- This ensures the event executes in the correct scopeconst effectFx = createEffect(() => { const scopeEvent = scopeBind(event); setTimeout(() => { scopeEvent(); }, 1000);});
Using units without useUnit
If youāre using events or effects in a framework without useUnit
, this may also lead to incorrect behavior related to scopes.
To fix this, pass the unit to the useUnit
hook and use the returned value:
import { event } from "./model.js";
const Component = () => { return <button onClick={() => event()}></button>;};
import { event } from "./model.js";import { useUnit } from "effector-react";
const Component = () => { const onEvent = useUnit(event);
return <button onClick={() => onEvent()}></button>;};
Using useUnit
is the recommended approach for working with units.
What is scope loss and why does it happen.
No Answer to Your Question?
If you couldnāt find the answer to your question, you can always ask the community: