Business logic with ease
Effector is a reactive state management library that models application business logic through events, stores, and effects. Unlike traditional imperative state managers, Effector uses a declarative approach where state changes propagate automatically through a dependency graph. You define what should happen when events occur, and Effector handles the reactive updates.
The library was designed to solve complexity in large-scale applications where coordinating state updates across multiple components becomes error-prone. It enforces strict immutability and unidirectional data flow while remaining framework-agnostic—you can use Effector with React, Vue, Svelte, or plain JavaScript. This makes it particularly valuable for teams working across multiple projects or migrating between frameworks.
Effector is used in production by teams building complex dashboards, real-time collaborative tools, and enterprise applications where predictable state behavior is critical. With weekly downloads exceeding 60,000, it has proven itself in applications ranging from small widgets to large-scale systems. The library's TypeScript-first design provides excellent type inference without requiring manual type annotations in most cases.
What sets Effector apart is its explicit modeling of side effects as first-class citizens. HTTP requests, timers, and other async operations are wrapped in 'effects' that expose pending states and success/failure events automatically. This eliminates boilerplate for loading states and error handling while maintaining full control over business logic flow.
import { createStore, createEvent, createEffect, sample } from 'effector';
// Define an effect for async API calls
const fetchUserFx = createEffect(async (userId) => {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
});
// Events are entry points for actions
const userIdChanged = createEvent();
const resetUser = createEvent();
// Stores hold reactive state
const $userId = createStore(null)
.on(userIdChanged, (_, userId) => userId)
.reset(resetUser);
const $user = createStore(null)
.on(fetchUserFx.doneData, (_, user) => user)
.reset(resetUser);
const $isLoading = createStore(false)
.on(fetchUserFx.pending, (_, pending) => pending);
const $error = createStore(null)
.on(fetchUserFx.failData, (_, error) => error.message)
.reset([fetchUserFx.done, resetUser]);
// Connect events to effects with sample
sample({
clock: userIdChanged,
filter: (userId) => userId !== null,
target: fetchUserFx,
});
// Subscribe to store updates
$user.watch((user) => {
if (user) console.log('User loaded:', user.name);
});
// Trigger the flow
userIdChanged(123);Complex form validation and submission: Model form fields as stores, validation as derived stores, and submission as effects. Effector automatically coordinates validation state, loading indicators, and error messages without manual wiring.
Real-time data synchronization: Handle WebSocket messages as events that update stores, with effects managing connection lifecycle. The reactive model ensures UI components always reflect the latest data without explicit update calls.
Multi-step workflows and wizards: Each step is an event, current step is a store, and navigation logic lives in event handlers. Side effects like API calls for each step are cleanly isolated, making the flow testable and maintainable.
Server-side rendering with hydration: Effector's scope API allows creating isolated state instances per request, preventing state leakage between users. Serialize store values on the server and rehydrate on the client seamlessly.
Feature flag and A/B testing systems: Store feature configurations in Effector stores, use derived stores for computed eligibility, and effects for remote config fetching. Changes propagate automatically to all dependent components without manual checks.
npm install effectorpnpm add effectorbun add effector