ReactJS - 高阶组件
ReactJS - 高阶组件 (HOCs)
Section titled “ReactJS - 高阶组件 (HOCs)”高阶组件 (Higher-Order Component, HOC) 是 React 中用于复用组件逻辑的一种高级技术。严格来说,HOC 本身并非 React API 的一部分。它们是 React 组合特性所衍生出来的一种模式。
具体来说,高阶组件是一个函数,它接收一个组件作为参数,并返回一个新的组件。
const EnhancedComponent = higherOrderComponent(WrappedComponent);为何使用 HOCs?
Section titled “为何使用 HOCs?”- 代码复用:在多个组件间共享逻辑,避免重复代码(例如,订阅数据源、日志记录、条件渲染)。
- Props 操作:添加或修改传递给被包装组件的 props。
- 抽象:抽象出复杂的逻辑或样板代码,使组件更简洁。
虽然 Hooks(例如 useEffect、useContext 和自定义 Hooks)已成为共享状态逻辑和副作用的更常用且通常更简单的方式,但 HOCs 仍然是一种有价值的模式,尤其适用于那些需要以声明式方式修改组件渲染或 props 的横切关注点(cross-cutting concerns)。
创建一个简单 HOC
Section titled “创建一个简单 HOC”让我们创建一个简单的 HOC,它向所包装的组件添加一个额外的 prop。
withExtraInfo.js (HOC)
Section titled “withExtraInfo.js (HOC)”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;MyComponent.jsx (将被包装的组件)
Section titled “MyComponent.jsx (将被包装的组件)”import React from 'react';
function MyComponent(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>{props.extraInfo}</p> {/* 这个 prop 来自 HOC */} </div> );}
export default MyComponent;App.js (使用 HOC)
Section titled “App.js (使用 HOC)”import React from 'react';import MyComponent from './MyComponent';import withExtraInfo from './withExtraInfo';
// 使用 HOC 增强 MyComponentconst 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!
HOCs 的关键考量:
Section titled “HOCs 的关键考量:”- 不要修改原始组件:HOC 应该返回一个新的组件,而不是修改输入的组件。
- 透传无关的 Props:HOCs 应该使用 spread operator (
{...props}) 透传所有与其特定关注点无关的 props。 - 组合:HOCs 可以组合在一起进行更复杂的转换。
- 命名约定:一个常见的约定是为 HOCs 添加
with前缀,例如withRouter或withSubscription。 - Refs 不会被透传:如果你需要访问被包装组件上的 ref,你需要使用
React.forwardRef。
HOCs 是创建可复用组件逻辑的强大模式。虽然自定义 Hooks 通常为共享状态逻辑提供了更直接的解决方案,但 HOCs 在修改 props、抽象渲染逻辑或集成需要组件的第三方库等任务中仍然很有用。
更多学习资源:
- React 关于 HOCs 的文档:https://react.dev/learn/HOCs (注意:新的 React 文档优先介绍 Hooks,但旧版文档包含良好的 HOC 信息。)
- 自定义 Hooks:https://react.dev/learn/reusing-logic-with-custom-hooks