Skip to content

ReactJS - 高阶组件

高阶组件 (Higher-Order Component, HOC) 是 React 中用于复用组件逻辑的一种高级技术。严格来说,HOC 本身并非 React API 的一部分。它们是 React 组合特性所衍生出来的一种模式。

具体来说,高阶组件是一个函数,它接收一个组件作为参数,并返回一个新的组件。

const EnhancedComponent = higherOrderComponent(WrappedComponent);
  • 代码复用:在多个组件间共享逻辑,避免重复代码(例如,订阅数据源、日志记录、条件渲染)。
  • Props 操作:添加或修改传递给被包装组件的 props。
  • 抽象:抽象出复杂的逻辑或样板代码,使组件更简洁。

虽然 Hooks(例如 useEffect、useContext 和自定义 Hooks)已成为共享状态逻辑和副作用的更常用且通常更简单的方式,但 HOCs 仍然是一种有价值的模式,尤其适用于那些需要以声明式方式修改组件渲染或 props 的横切关注点(cross-cutting concerns)。

让我们创建一个简单的 HOC,它向所包装的组件添加一个额外的 prop。

import React from 'react';
// 这是一个高阶组件
const withExtraInfo = (WrappedComponent) => {
// 它返回一个新的函数式组件
const ComponentWithExtraInfo = (props) => {
const extraInfo = "This info is from the HOC!";
// 传递现有 props 以及新 prop
return <WrappedComponent {...props} extraInfo={extraInfo} />;
};
// 为调试设置一个 display name 是个好习惯
ComponentWithExtraInfo.displayName = `WithExtraInfo(${getDisplayName(WrappedComponent)})`;
return ComponentWithExtraInfo;
};
// 获取组件 display name 的辅助函数
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
export default withExtraInfo;
import React from 'react';
function MyComponent(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>{props.extraInfo}</p> {/* 这个 prop 来自 HOC */}
</div>
);
}
export default MyComponent;
import React from 'react';
import MyComponent from './MyComponent';
import withExtraInfo from './withExtraInfo';
// 使用 HOC 增强 MyComponent
const MyComponentWithExtraInfo = withExtraInfo(MyComponent);
function App() {
return (
<div>
<MyComponentWithExtraInfo name="User" />
</div>
);
}
export default App;

当这个 App 组件渲染时,MyComponentWithExtraInfo 将是 MyComponent,但被 withExtraInfo HOC 注入了一个额外的 extraInfo prop。输出将显示: Hello, User! This info is from the HOC!

  • 不要修改原始组件:HOC 应该返回一个新的组件,而不是修改输入的组件。
  • 透传无关的 Props:HOCs 应该使用 spread operator ({...props}) 透传所有与其特定关注点无关的 props。
  • 组合:HOCs 可以组合在一起进行更复杂的转换。
  • 命名约定:一个常见的约定是为 HOCs 添加 with 前缀,例如 withRouter 或 withSubscription。
  • Refs 不会被透传:如果你需要访问被包装组件上的 ref,你需要使用 React.forwardRef。

HOCs 是创建可复用组件逻辑的强大模式。虽然自定义 Hooks 通常为共享状态逻辑提供了更直接的解决方案,但 HOCs 在修改 props、抽象渲染逻辑或集成需要组件的第三方库等任务中仍然很有用。

更多学习资源: