{"id":18061,"library":"react-mixin","title":"React Mixin Utility for ES6 Classes","description":"react-mixin is a utility library designed to enable the use of traditional React mixins with ES6/TypeScript classes, addressing the absence of built-in support for this pattern in React's class-based components. While React itself has deprecated mixins in favor of Higher-Order Components and Hooks, this package serves as a specific migration path for legacy codebases that must integrate existing mixins with modern class syntax. The current stable version is 5.0.0, which notably adapted to React's `UNSAFE_` lifecycle methods. The library provides mechanisms to apply mixins to class prototypes for instance methods and to the classes themselves for static properties like `defaultProps` and `propTypes`. It differentiates itself by offering clear error handling for conflicting method names (instead of silent overwrites) and supporting an optional decorator syntax, allowing developers to manage mixins in a structured way within their class definitions. However, it explicitly advocates for avoiding mixins in new development.","status":"deprecated","version":"5.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/brigand/react-mixin","tags":["javascript","react","mixin","es6","class","smart-mixin"],"install":[{"cmd":"npm install react-mixin","lang":"bash","label":"npm"},{"cmd":"yarn add react-mixin","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-mixin","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"For ESM, use a default import. For CommonJS, use `require()`. In legacy browser contexts, `window.reactMixin` or AMD modules might be exposed via tools like wzrd.in.","wrong":"const reactMixin = require('react-mixin'); // Correct for CJS, but prefer ESM for modern apps.","symbol":"reactMixin","correct":"import reactMixin from 'react-mixin';"},{"note":"Used to apply mixins that define static class properties like `defaultProps` or `propTypes` to the class constructor itself, not its prototype.","wrong":"const reactMixin = require('react-mixin'); reactMixin(MyClass, myMixin); // 'onClass' method is specifically for static properties.","symbol":"reactMixin.onClass","correct":"import reactMixin from 'react-mixin'; reactMixin.onClass(MyClass, myMixin);"},{"note":"Available since version 5.0.0, this utility converts a mixin's deprecated lifecycle methods (e.g., `componentWillMount`) to their `UNSAFE_` prefixed equivalents for compatibility with React 16.3+.","wrong":"import { toUnsafe } from 'react-mixin'; // 'toUnsafe' is a separate export, not a named export from the main module.","symbol":"toUnsafe","correct":"import toUnsafe from 'react-mixin/toUnsafe';"},{"note":"Requires Babel with ES7 decorator support. This creates a new class via prototypical inheritance, rather than mutating the original class.","symbol":"reactMixin.decorate","correct":"import reactMixin from 'react-mixin'; @reactMixin.decorate(myMixin) class MyClass {}"}],"quickstart":{"code":"import React from 'react';\nimport reactMixin from 'react-mixin';\nimport toUnsafe from 'react-mixin/toUnsafe';\n\n// Define a simple React Component\nclass MyComponent extends React.Component {\n  constructor(props) {\n    super(props);\n    this.state = { count: 0 };\n    // Autobinding is not provided by react-mixin; explicit binding is necessary.\n    this.handleClick = this.handleClick.bind(this);\n  }\n\n  // Example method that might be part of or overridden by a mixin\n  handleClick() {\n    this.setState(prevState => ({ count: prevState.count + 1 }));\n  }\n\n  render() {\n    return (\n      <div>\n        <h1>Count: {this.state.count}</h1>\n        <button onClick={this.handleClick}>Increment</button>\n        <p>Props: {JSON.stringify(this.props)}</p>\n      </div>\n    );\n  }\n}\n\n// Define example mixins\nconst MyStateMixin = {\n  getInitialState() { // This method will be merged\n    return { mixedData: 'initial value' };\n  },\n  componentDidMount() {\n    console.log('MyStateMixin mounted!');\n  },\n  // Version 5.0+ requires UNSAFE_ prefix for these lifecycle methods\n  UNSAFE_componentWillMount() {\n    console.log('MyStateMixin UNSAFE_componentWillMount!');\n  }\n};\n\nconst MyPropsMixin = {\n  // This will be merged at the class level using .onClass\n  getDefaultProps() {\n    return { defaultPropFromMixin: 'default' };\n  },\n  componentDidUpdate(prevProps, prevState) {\n    console.log('MyPropsMixin updated!');\n  }\n};\n\n// --- Apply mixins to the component's prototype ---\nreactMixin(MyComponent.prototype, MyStateMixin);\n\n// --- Apply mixins with UNSAFE_ method conversion for v5+ ---\n// If MyPropsMixin had componentWillMount, we'd use toUnsafe on it.\n// For demonstration, let's assume it did and apply it through toUnsafe for clarity.\nconst fixedPropsMixin = toUnsafe(MyPropsMixin);\nreactMixin(MyComponent.prototype, fixedPropsMixin);\n\n// --- Apply mixins to the class itself for static properties (e.g., getDefaultProps) ---\nreactMixin.onClass(MyComponent, MyPropsMixin); // Note: use the original mixin here for getDefaultProps merging.\n\n// --- Example using the decorator syntax (requires Babel with decorator support) ---\n// @reactMixin.decorate(MyStateMixin)\n// class DecoratedComponent extends React.Component {\n//   render() { return <div>Decorated Component!</div>; }\n// }\n\n// Simulate instantiation to show applied props/state (in a real app, you'd render this to DOM)\nconsole.log(\"Component created with mixins applied. Check console for lifecycle logs.\");\nconst instance = new MyComponent({ customInput: 'test' });\nconsole.log('Initial component state:', instance.state); // Should include mixedData\nconsole.log('Initial component props (merged with defaults):', instance.props); // Should include defaultPropFromMixin\n","lang":"typescript","description":"This code demonstrates how to apply mixins to React ES6 classes using `react-mixin`. It covers applying mixins to the prototype for instance methods, using `reactMixin.onClass` for static class properties like `getDefaultProps`, and utilizing `react-mixin/toUnsafe` for v5's `UNSAFE_` lifecycle method compatibility."},"warnings":[{"fix":"For new features, utilize Higher-Order Components or React Hooks instead of mixins. For legacy code, ensure `react-mixin` is used minimally and consider refactoring to modern React patterns over time.","message":"React mixins are a deprecated pattern. The `react-mixin` library itself is primarily intended as a migration path for legacy code using ES6 classes with mixins. New development should strongly prefer Higher-Order Components (HOCs) or Hooks for code reuse and shared logic.","severity":"deprecated","affected_versions":"*"},{"fix":"Upgrade `react-mixin` to `^5.0.0`. Rename affected mixin methods (e.g., `componentWillMount` to `UNSAFE_componentWillMount`) or wrap the mixin with `toUnsafe()` before applying it: `reactMixin(MyClass.prototype, toUnsafe(myMixin));`.","message":"Version 5.0 of `react-mixin` aligns with React's deprecation of `componentWillMount`, `componentWillReceiveProps`, and `componentWillUpdate`. Mixins defining these methods will no longer function correctly and must be renamed to their `UNSAFE_` counterparts (e.g., `UNSAFE_componentWillMount`) or processed with the `react-mixin/toUnsafe` utility.","severity":"breaking","affected_versions":">=5.0"},{"fix":"Explicitly bind methods in your class constructor (e.g., `this.myMethod = this.myMethod.bind(this);`), or use public class fields with arrow functions (`myMethod = () => {}`) if your build setup supports it.","message":"`react-mixin` does not automatically bind `this` context for methods within mixins or ES6 class methods, unlike `React.createClass`. Method callbacks (e.g., event handlers) will lose `this` context if not explicitly bound.","severity":"gotcha","affected_versions":"*"},{"fix":"Be aware that the decorated class is a new constructor. If strict class identity is required, apply mixins directly to the prototype or class using `reactMixin(Foo.prototype, mixin)` or `reactMixin.onClass(Foo, mixin)`.","message":"When using `reactMixin.decorate(mixin)` as an ES7 decorator, it performs prototypical inheritance, which means it returns a *new* class rather than mutating the original class in place. This can have implications for class identity checks or direct references to the original class.","severity":"gotcha","affected_versions":"*"},{"fix":"Inspect console errors for conflicting method names when applying multiple mixins. Refactor mixins to avoid name collisions or re-evaluate the need for multiple mixins if common functionality can be abstracted differently.","message":"`react-mixin` provides errors instead of silently overwriting conflicting methods from multiple mixins, with the exception of specific whitelisted methods (like `getDefaultProps` and `getInitialState`) which are explicitly designed for merging.","severity":"gotcha","affected_versions":"*"}],"env_vars":null,"last_verified":"2026-04-25T00:00:00.000Z","next_check":"2026-07-24T00:00:00.000Z","problems":[{"fix":"Explicitly bind the method in the class constructor: `this.myMethod = this.myMethod.bind(this);` or define the method using an arrow function for class fields if supported by your build setup: `myMethod = () => { /* ... */ }`.","cause":"ES6 class methods and mixin methods applied to ES6 classes are not autobound by default, unlike `React.createClass`. The `this` context is lost when the method is called as a callback (e.g., event handler).","error":"TypeError: Cannot read properties of undefined (reading 'setState') OR 'this' is undefined in mixin method."},{"fix":"Upgrade `react-mixin` to `^5.0.0` and either rename the affected mixin methods (e.g., `componentWillMount` to `UNSAFE_componentWillMount`) or wrap the mixin with `toUnsafe()` before applying it: `reactMixin(MyClass.prototype, toUnsafe(myMixin));`.","cause":"`react-mixin` versions prior to 5.0 used deprecated React lifecycle methods. Version 5.0+ requires the `UNSAFE_` prefix for these methods or conversion via `react-mixin/toUnsafe`.","error":"Warning: componentWillMount has been renamed, and is not recommended for use. OR Mixin lifecycle method (e.g., `componentWillMount`) is not firing in React v16.3+."},{"fix":"Use `reactMixin.onClass(MyClass, myMixin)` to apply mixins that define static or class-level properties. This ensures the properties are correctly merged with the class definition.","cause":"Static class properties (e.g., `defaultProps`, `propTypes`, or methods like `getDefaultProps`) from mixins need to be applied to the class constructor itself, not its prototype.","error":"TypeError: Cannot read properties of undefined (reading 'defaultProps') OR Static properties from a mixin like `getDefaultProps` or `propTypes` are not applied to the component."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}