5 Ways to Reuse and Extend React Component State Logic
This article explains five approaches—Mixins, Class Inheritance, Higher‑Order Components, Render Props, and Hooks—for reusing and extending state logic in React components, comparing their advantages, drawbacks, and providing code examples to illustrate each method.
How can you reuse and extend React component state logic? This article presents five solutions.
Mixins
Class Inheritance
Higher‑Order Component (HOC)
Render Props
React Hooks
Below each method is introduced in detail.
1. Mixins
Mixins copy an object’s properties onto another object to achieve code reuse. They were introduced to solve reuse problems but are no longer supported in modern React because they cause hidden dependencies, tight coupling, name‑collision issues, and increased complexity.
Object.assign is a common method for copying properties, but unlike Mixins it does not copy prototype‑chain properties.
Since React has dropped Mixins, the article does not cover their usage further; refer to legacy resources for older React versions.
2. Class Inheritance
Class inheritance can reuse logic by extending a parent component, but React (and Facebook) discourage it. Inheritance makes components harder to read, forces developers to jump between parent and child code, and can overwrite lifecycle methods. Composition is preferred because it keeps components focused on a single responsibility and improves reusability, testability, and predictability.
3. Higher‑Order Component (HOC)
A HOC is a function that takes a component as an argument and returns a new component. It works like a decorator and can be implemented via inheritance inversion or props proxy.
Two implementations:
Inheritance‑based HOC (reverse inheritance)
Props‑proxy HOC (attribute proxy)
Example of an inheritance‑based HOC (simplified):
<code>export default const HOC = (WrappedComponent) => class NewComponent extends WrappedComponent {
componentWillMount() {
console.log('Here the original component lifecycle is modified');
}
render() {
const element = super.render();
const newProps = { ...this.props, style: { color: 'red' } };
return React.cloneElement(element, newProps, element.props.children);
}
};
</code>Proxy‑based HOC example that wraps
Profileand
Homewith a
Containercomponent:
<code>// app.js
import React from "react";
import ReactDOM from "react-dom";
import Profile from "./components/Profile";
import Home from "./components/Home";
import "./styles.css";
function App() {
return (
<div className="App">
<Profile name="Airing" />
<Home />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
</code> <code>// Container.js
import React, { Component } from "react";
import "../styles.css";
export default title => WrappedComponent => class Container extends Component {
render() {
return (
<div className="container">
<header className="header">{title}</header>
<WrappedComponent url="https://me.ursb.me" {...this.props} />
</div>
);
}
};
</code>HOC usage with
Profileand
Homecomponents:
<code>// Profile.js
import React, { Component } from "react";
import WrappedComponent from "./WrappedComponent";
class Profile extends Component {
render() {
return (
<>
<p>Author: {this.props.name}</p>
<p>Blog: {this.props.url}</p>
<p>Component A</p>
</>
);
}
}
export default WrappedComponent("Profile")(Profile);
</code> <code>// Home.js
import React, { Component } from "react";
import WrappedComponent from "./WrappedComponent";
class Home extends Component {
render() {
return (
<>
<p>Component B</p>
</>
);
}
}
export default WrappedComponent("Home")(Home);
</code>HOCs are widely used, e.g., Redux’s
connectfunction and Ant Design’s
Form.create()are HOC implementations.
Drawbacks of HOCs include wrapper hell (deep nesting), the need to manually set
displayName, poor TypeScript typing, ref forwarding issues, manual copying of static properties, and unintended prop leakage.
4. Render Props
Render Props pass a function as a prop to control what a component renders. The pattern is similar to React’s Context API, where a consumer receives a function that returns JSX.
<code>class App extends React.Component {
render() {
return (
<ThemeProvider>
<ThemeContext.Consumer>
{val => <div>{val}</div>}
</ThemeContext.Consumer>
</ThemeProvider>
);
}
}
</code>Render Props suffer from the same wrapper‑hell problem as HOCs.
5. React Hooks
Hooks solve the problems of Mixins, HOCs, and Render Props. They avoid naming conflicts, eliminate wrapper hell, and bring the benefits of functional components while providing state, lifecycle, and ref capabilities via
useState,
useEffect,
useRef, etc.
The article promises a deeper dive into Hook implementations in the next installment.
QQ Music Frontend Team
QQ Music Web Frontend Team
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.