fork API
import { fork, type Scope } from "effector";fork creates an isolated scope of your app. Use it for SSR, testing, or any case where you need to run logic in a safe copy without touching global units.
How it works
- Call
forkto get a new scope. - If
valuesorhandlersare provided, they are applied when the scope is created. - Units run in that scope operate on isolated state and overridden handlers.
- Read state via
scope.getState(store)or serialize it withserialize.
fork configuration forms
Form | Description |
|---|---|
fork() | Creates a fresh scope with no prefilled data or handler overrides. |
fork({ values?, handlers? }) | Creates a scope with initial store values and custom effect handlers. |
fork(domain, options?) | Legacy form that requires domain. Prefer fork({ values?, handlers? }) unless you need old signature compatibility. |
Configurations
fork()
Creates a new application scope with default behavior.
- Formula
fork(): Scope- Type
type SerializedState = Record<string, unknown>;type StorePair<T = unknown> = [StoreWritable<T>, T];
export function fork(config?: { values?: StorePair<any>[] | SerializedState; handlers?: Array<[Effect<any, any, any>, Function]>;}): Scope;-
Notes
- Returns a fresh scope without prefilled stores or handler overrides.
- Use when you need a clean state (e.g., first render on the server).
-
Example
import { createStore, createEvent, fork, allSettled } from "effector";
const inc = createEvent();const dec = createEvent();const $counter = createStore(0);
$counter.on(inc, (value) => value + 1);$counter.on(dec, (value) => value - 1);
const scopeA = fork();const scopeB = fork();
await allSettled(inc, { scope: scopeA });await allSettled(dec, { scope: scopeB });
console.log($counter.getState()); // => 0console.log(scopeA.getState($counter)); // => 1console.log(scopeB.getState($counter)); // => -1- Returns
A new scope.
fork({ values?, handlers? })
Adds initial store values and overrides effect handlers inside the scope.
- Formula
fork({ values?, // e.g. [[$store, value], ...] or serialized object handlers?, // e.g. [[effect, handler], ...]}): Scope- Type
type SerializedState = Record<string, unknown>;type StorePair<T = unknown> = [StoreWritable<T>, T];
export function fork(config?: { values?: StorePair<any>[] | SerializedState; handlers?: Array<[Effect<any, any, any>, Function]>;}): Scope;-
Notes
valuescan be an array of tuples[$store, value]or a serialized state object (usually fromserialize); tuples are preferred.handlersaccepts only an array of tuples to override effect handlers; overrides apply only within the created scope.- Values and handlers are applied once at scope creation and are not updated automatically.
-
Examples
Set initial state and replace a handler in a test:
import { createEffect, createStore, fork, allSettled } from "effector";
const fetchFriendsFx = createEffect<{ limit: number }, string[]>(async ({ limit }) => { return [];});const $user = createStore("guest");const $friends = createStore<string[]>([]);
$friends.on(fetchFriendsFx.doneData, (_, result) => result);
const testScope = fork({ values: [[$user, "alice"]], handlers: [[fetchFriendsFx, () => ["bob", "carol"]]],});
await allSettled(fetchFriendsFx, { scope: testScope, params: { limit: 10 },});
console.log(testScope.getState($friends));// => ['bob', 'carol']Create a scope from serialized state:
import { fork } from "effector";
const serialized = { userSid: "alice", ageSid: 21,};
const scope = fork({ values: serialized });- Returns
A new scope with applied values and handlers.
fork(domain, options?)
Legacy form that requires a domain; keep only for compatibility with older code.
Deprecated
Use fork({ values?, handlers? }) because fork tracks units automatically without a domain.
- Formula
fork(domain, { values?, // e.g. [[$store, value], ...] or serialized object handlers?, // e.g. [[effect, handler], ...]}): Scope- Type
type SerializedState = Record<string, unknown>;
export function fork( domain: Domain, config?: { values?: SerializedState | Array<[StoreWritable<any>, any]>; handlers?: Array<[Effect<any, any, any>, Function]>; },): Scope;-
Notes
- Pass
domainonly if your project still depends on the old signature. - Allowed
valuesandhandlersformats match the configuration withoutdomain.
- Pass
-
Example
import { createDomain, createStore, fork } from "effector";
const app = createDomain();const $flag = app.createStore(false);
const scope = fork(app, { values: [[$flag, true]],});
console.log(scope.getState($flag)); // => true- Returns
A new scope attached to the provided domain.
Related API and articles
- API
- Articles