Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
compose
✓ import { compose } from 'recompose';
✗ const compose = require('recompose').compose;
While CommonJS `require` works, ESM `import` is the recommended and modern practice. Ensure bundler support for CJS if mixing.
withState
✓ import { withState } from 'recompose';
✗ import withState from 'recompose/withState';
Individual HOCs can be imported directly, but named imports from the main package are generally preferred for tree-shaking and consistency.
withHandlers
✓ import { withHandlers } from 'recompose';
✗ const { withHandlers } = require('recompose');
TypeScript users will benefit from `@types/recompose` for correct prop inference, though type inference can be tricky with deeply nested HOCs.
This quickstart demonstrates creating a stateful functional React component using `recompose` HOCs like `compose`, `withState`, `withHandlers`, and `lifecycle` for managing count, message, and reacting to mount/update events.
import React from 'react';
import { compose, withState, withHandlers, lifecycle } from 'recompose';
interface CounterProps {
count: number;
increment: () => void;
decrement: () => void;
message: string;
}
const CounterDisplay: React.FC<CounterProps> = ({ count, increment, decrement, message }) => (
<div>
<h1>{message}</h1>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
const enhance = compose<
CounterProps,
{ initialCount?: number; initialMessage?: string }
>(
withState('count', 'setCount', ({ initialCount = 0 }) => initialCount),
withState('message', 'setMessage', ({ initialMessage = 'Hello Recompose!' }) => initialMessage),
withHandlers({
increment: ({ setCount }) => () => setCount((prevCount: number) => prevCount + 1),
decrement: ({ setCount }) => () => setCount((prevCount: number) => prevCount - 1)
}),
lifecycle({
componentDidMount() {
console.log('Counter component mounted.');
this.props.setMessage('Welcome to the Recompose Counter!');
},
componentDidUpdate(prevProps: CounterProps) {
if (this.props.count !== prevProps.count) {
console.log(`Count changed from ${prevProps.count} to ${this.props.count}`);
}
}
})
);
const EnhancedCounter = enhance(CounterDisplay);
// Example usage in an application (e.g., App.tsx)
// function App() {
// return (
// <div style={{ padding: '20px' }}>
// <EnhancedCounter initialCount={5} />
// </div>
// );
// }
// export default App;
Debug
Known issues
breakingThe `withStateHandler` HOC's behavior changed in v0.30.0, making state changes more similar to `React.setState`. This might affect how state updates are handled, especially with synchronous vs. asynchronous updates or the merging of partial state objects. Review existing usages to ensure compatibility.fixThoroughly test components using `withStateHandler` after upgrading to v0.30.0. Adapt state updater functions to explicitly merge state if necessary, mirroring React's `setState` behavior.
affects: >=0.30.0
breakingIn v0.26.0, `recompose` removed 'eager optimizations' (where `createElement` was sometimes replaced with direct function calls). This change was a response to various issues and could alter rendering behavior, potentially impacting performance or causing unexpected side effects in certain scenarios.fixNo direct fix; this was a library-level change. Monitor component behavior and performance after upgrading, especially for components that previously exhibited odd rendering issues or relied on specific optimization characteristics.
affects: >=0.26.0
gotchaVersion 0.25.0 introduced 'production only optimizations' which meant certain eager factory optimizations were only applied in production environments. This could lead to behavioral differences or unexpected issues during development that were not present in production builds.fixBe aware of potential discrepancies between development and production environments. Test critical flows in both environments to catch issues related to these specific optimizations. Upgrade to >=0.26.0 which removed these optimizations.
affects: >=0.25.0 <0.26.0
deprecated`recompose` is effectively abandoned by its author in favor of React Hooks (introduced in React 16.8). While existing code will continue to work, active development, new features, and compatibility fixes for future React versions are not expected.fixFor new development, use React Hooks (`useState`, `useEffect`, `useCallback`, `useMemo`, `useReducer`, `useContext`) which offer similar capabilities natively. Consider migrating existing `recompose` HOCs to Hooks over time for better maintainability and future compatibility.
affects: >=0.30.0
deprecatedThe `lifecycle` HOC internally uses deprecated React lifecycle methods (`componentWillMount`, `componentWillReceiveProps`, `componentWillUpdate`). Using these methods, even indirectly through `recompose`, will trigger `UNSAFE_` warnings in modern React versions (16.3+), indicating they may cause issues with upcoming features like Concurrent Mode.fixAvoid using the `lifecycle` HOC if possible. Replace its functionality with React Hooks (`useEffect`) if migrating components, or consider custom HOCs that use `componentDidMount` / `componentDidUpdate` where appropriate, avoiding `UNSAFE_` methods.
affects: >=0.27.0
deprecated`recompose` uses `React.createFactory()` internally, which was deprecated in React 16.13.1 and will be removed in a future major release. This will cause warnings and eventually breakage with newer React versions.fixThere is no direct fix within `recompose` as it is an internal dependency usage. This further reinforces the recommendation to migrate away from `recompose` to React Hooks for long-term compatibility with React.
affects: >=0.30.0
Errors
Common errors & fixes
TypeError: (0 , _recompose.compose) is not a function
Attempting to use `compose` with a CommonJS `require` call where the `recompose` package is designed for ES module imports or a specific CJS export structure is not being respected.
fixEnsure you are using `import { compose } from 'recompose';` in an ES module context or configure your bundler (e.g., Webpack, Rollup) to correctly handle interop between CommonJS and ES modules. If strictly in a CommonJS environment, verify the exact export structure or use `const compose = require('recompose').compose;`. Invariant Violation: You supplied a function as the second argument to withState, but it must be an object.
Incorrect usage of `withStateHandlers`. This HOC expects an object as its second argument, where keys are handler names and values are functions that return a new state object. It is often confused with `withState` which takes a function for the initial state and a string for the setter name.
fixRefactor `withStateHandlers` calls. The second argument should be an object mapping updater names to functions that receive the current state and props, and return a *partial* state object. Example: `withStateHandlers({ value: '' }, { updateValue: () => (event) => ({ value: event.target.value }) })`. Warning: componentWillMount has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-lifecycles for details.
This warning occurs because the `lifecycle` HOC in `recompose` uses deprecated (and now prefixed `UNSAFE_`) React lifecycle methods like `componentWillMount`.
fixAvoid using `lifecycle` for new functionality. For existing code, consider refactoring the logic into React Hooks (`useEffect`) or standard React class component `componentDidMount` if a full migration isn't feasible immediately. React discourages the use of `UNSAFE_` methods.
Property 'someProp' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<InferableComponentEnhancerWithProps<any, any>, any, any>> & Readonly<{ children?: ReactNode; }> & Readonly<OriginalProps>'.
This TypeScript error indicates a mismatch in prop types when composing HOCs with `recompose`. TypeScript struggles to correctly infer the final props passed to the base component, especially with complex HOC chains, often leading to 'any' or incorrect type unions.
fixExplicitly define and pass prop types at each stage of the HOC composition using generics in `compose` or by defining the `ComponentEnhancer` types. Ensure the final component's props interface correctly extends all injected props from the HOCs. Consult `@types/recompose` definitions for correct `ComponentEnhancer` or `InferableComponentEnhancerWithProps` usage.
Audit
Dependencies
reactrequiredPeer dependency for all versions, as recompose extends React component functionality.