Effector React Bindings
effector-react provides the official React bindings for the effector state management library, allowing developers to seamlessly integrate effector's reactive, event-driven state model with their React applications. The current stable version is 23.3.0, frequently updated in parallel with the core effector library. Its key differentiators include a declarative, algebraic effects paradigm for managing complex application logic, which promotes clear separation of concerns between business logic and UI. It offers optimized React hooks, notably useUnit, for consuming effector stores, events, and effects, ensuring efficient component re-renders and simplified access to application state and actions. The library also boasts strong TypeScript support and recently added compatibility for React 19.
Common errors
-
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
cause Attempting to call an `effector-react` hook (like `useUnit`, `useStore`, `createGate`) outside of a React functional component or a custom hook.fixEnsure `effector-react` hooks are only invoked within the render function of a React functional component or at the top level of another custom hook. Check for conditional hook calls or calls within regular JavaScript functions. -
Unhandled Rejection (TypeError): Cannot read properties of undefined (reading 'sid')
cause This error often indicates an issue with Effector units losing their identity or being incorrectly passed, frequently seen with old CommonJS `require()` imports or issues with the Babel/SWC plugin's SID generation.fixVerify that you are using ES module imports (`import ... from '...'`) throughout your Effector codebase. Ensure the `@effector/babel-plugin` (or SWC equivalent) is correctly installed and configured in your build setup, especially if using HMR or hot reloading. Update to the latest `effector` and `effector-react` versions. -
TypeError: (0 , effector_react__WEBPACK_IMPORTED_MODULE_1__.useUnit) is not a function
cause This typically means `useUnit` was not correctly imported or the module resolution failed. This can happen with incorrect build configurations, version mismatches, or CJS/ESM interop issues.fixCheck your import statement: `import { useUnit } from 'effector-react'`. Confirm `effector-react` is correctly installed. Ensure your build tool (Webpack, Babel, etc.) is configured to handle ES Modules from `node_modules` correctly, especially if you have custom aliases or transformations.
Warnings
- breaking Older CommonJS `require()` imports are no longer officially supported for `effector` and its ecosystem, including `effector-react`, in recent major versions. Modern applications should use ES module `import` syntax.
- gotcha Effector's core library (and by extension `effector-react`) relies heavily on a Babel/SWC plugin for optimal development experience, including Hot Module Replacement (HMR), improved error messages, and better debugging. Without it, some advanced features or ergonomics might be limited.
- gotcha Ensure `react` and `effector` peer dependency versions are compatible. `effector-react` 23.3.0 specifically requires `react` `>=16.8.0 <20.0.0` and `effector` `^23.0.0`. Mismatched versions can lead to runtime errors or unexpected behavior.
- deprecated The `useStore` hook is largely superseded by `useUnit` for consuming effector units. While still functional for single stores, `useUnit` offers a more powerful and flexible API for combining multiple units and actions.
Install
-
npm install effector-react -
yarn add effector-react -
pnpm add effector-react
Imports
- useUnit
const useUnit = require('effector-react')import { useUnit } from 'effector-react' - createGate
const createGate = require('effector-react')import { createGate } from 'effector-react' - useStore
import useStore from 'effector-react'
import { useStore } from 'effector-react'
Quickstart
import { createStore, createEvent } from 'effector';
import { useUnit } from 'effector-react';
import React from 'react'; // Assuming React is imported for JSX
const inputText = createEvent<string>();
const $text = createStore<string>('').on(inputText, (_, text) => text);
const $size = $text.map(text => text.length);
const Form = () => {
const { text, size } = useUnit({
text: $text,
size: $size,
});
const handleTextChange = useUnit(inputText);
return (
<form>
<label htmlFor="text-input">Enter text:</label>
<input
id="text-input"
type="text"
onChange={e => handleTextChange(e.currentTarget.value)}
value={text}
aria-label="Text input for form"
/>
<p>Length: {size}</p>
</form>
);
};
// To render this component (e.g., in App.js or index.js):
// import ReactDOM from 'react-dom/client';
// const root = ReactDOM.createRoot(document.getElementById('root'));
// root.render(<Form />);