{"id":15227,"library":"recompose","title":"recompose","description":"recompose is a JavaScript utility library for React, providing a collection of higher-order components (HOCs) and utility functions designed to enhance functional component patterns. It allows developers to compose multiple concerns into a single component, such as managing local state (`withState`), handling side effects (`lifecycle`), mapping props (`mapProps`), and creating event handlers (`withHandlers`). The current stable version is 0.30.0, released in late 2018. The author explicitly announced the discontinuation of active maintenance in October 2018, recommending React Hooks as a superior alternative that addresses the same problems and more. Its primary differentiator was enabling a purely functional approach to component logic before the native React Hooks API existed, offering a declarative way to abstract component logic and state management without relying on class components.","status":"abandoned","version":"0.30.0","language":"javascript","source_language":"en","source_url":"https://github.com/acdlite/recompose","tags":["javascript","react","higher-order","components","microcomponentization","toolkit","utilities","composition"],"install":[{"cmd":"npm install recompose","lang":"bash","label":"npm"},{"cmd":"yarn add recompose","lang":"bash","label":"yarn"},{"cmd":"pnpm add recompose","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for all versions, as recompose extends React component functionality.","package":"react","optional":false}],"imports":[{"note":"While CommonJS `require` works, ESM `import` is the recommended and modern practice. Ensure bundler support for CJS if mixing.","wrong":"const compose = require('recompose').compose;","symbol":"compose","correct":"import { compose } from 'recompose';"},{"note":"Individual HOCs can be imported directly, but named imports from the main package are generally preferred for tree-shaking and consistency.","wrong":"import withState from 'recompose/withState';","symbol":"withState","correct":"import { withState } from 'recompose';"},{"note":"TypeScript users will benefit from `@types/recompose` for correct prop inference, though type inference can be tricky with deeply nested HOCs.","wrong":"const { withHandlers } = require('recompose');","symbol":"withHandlers","correct":"import { withHandlers } from 'recompose';"}],"quickstart":{"code":"import React from 'react';\nimport { compose, withState, withHandlers, lifecycle } from 'recompose';\n\ninterface CounterProps {\n  count: number;\n  increment: () => void;\n  decrement: () => void;\n  message: string;\n}\n\nconst CounterDisplay: React.FC<CounterProps> = ({ count, increment, decrement, message }) => (\n  <div>\n    <h1>{message}</h1>\n    <p>Count: {count}</p>\n    <button onClick={increment}>Increment</button>\n    <button onClick={decrement}>Decrement</button>\n  </div>\n);\n\nconst enhance = compose<\n  CounterProps,\n  { initialCount?: number; initialMessage?: string }\n>(\n  withState('count', 'setCount', ({ initialCount = 0 }) => initialCount),\n  withState('message', 'setMessage', ({ initialMessage = 'Hello Recompose!' }) => initialMessage),\n  withHandlers({\n    increment: ({ setCount }) => () => setCount((prevCount: number) => prevCount + 1),\n    decrement: ({ setCount }) => () => setCount((prevCount: number) => prevCount - 1)\n  }),\n  lifecycle({\n    componentDidMount() {\n      console.log('Counter component mounted.');\n      this.props.setMessage('Welcome to the Recompose Counter!');\n    },\n    componentDidUpdate(prevProps: CounterProps) {\n      if (this.props.count !== prevProps.count) {\n        console.log(`Count changed from ${prevProps.count} to ${this.props.count}`);\n      }\n    }\n  })\n);\n\nconst EnhancedCounter = enhance(CounterDisplay);\n\n// Example usage in an application (e.g., App.tsx)\n// function App() {\n//   return (\n//     <div style={{ padding: '20px' }}>\n//       <EnhancedCounter initialCount={5} />\n//     </div>\n//   );\n// }\n// export default App;\n","lang":"typescript","description":"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."},"warnings":[{"fix":"Thoroughly 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.","message":"The `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.","severity":"breaking","affected_versions":">=0.30.0"},{"fix":"No 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.","message":"In 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.","severity":"breaking","affected_versions":">=0.26.0"},{"fix":"Be 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.","message":"Version 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.","severity":"gotcha","affected_versions":">=0.25.0 <0.26.0"},{"fix":"For 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.","message":"`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.","severity":"deprecated","affected_versions":">=0.30.0"},{"fix":"Avoid 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.","message":"The `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.","severity":"deprecated","affected_versions":">=0.27.0"},{"fix":"There 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.","message":"`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.","severity":"deprecated","affected_versions":">=0.30.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure 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;`.","cause":"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.","error":"TypeError: (0 , _recompose.compose) is not a function"},{"fix":"Refactor `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 }) })`.","cause":"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.","error":"Invariant Violation: You supplied a function as the second argument to withState, but it must be an object."},{"fix":"Avoid 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.","cause":"This warning occurs because the `lifecycle` HOC in `recompose` uses deprecated (and now prefixed `UNSAFE_`) React lifecycle methods like `componentWillMount`.","error":"Warning: componentWillMount has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-lifecycles for details."},{"fix":"Explicitly 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.","cause":"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.","error":"Property 'someProp' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<InferableComponentEnhancerWithProps<any, any>, any, any>> & Readonly<{ children?: ReactNode; }> & Readonly<OriginalProps>'."}],"ecosystem":"npm"}