高阶组件(Higher-Order Component,HOC)是一种用于在 React 中复用组件逻辑的技术。以下是几个常见的 HOC 使用案例,以及详细的代码示例。
1. 日志记录 HOC
这个高阶组件将在每次组件更新时记录日志。
LoggingHOC.js
import React from 'react';
const withLogging = (WrappedComponent) => {
return class extends React.Component {
componentDidMount() {
console.log(`${WrappedComponent.name} mounted`);
}
componentDidUpdate() {
console.log(`${WrappedComponent.name} updated`);
}
componentWillUnmount() {
console.log(`${WrappedComponent.name} will unmount`);
}
render() {
return <WrappedComponent {...this.props} />;
}
};
};
export default withLogging;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
使用日志记录 HOC
// src/App.js
import React from 'react';
import withLogging from './LoggingHOC';
const MyComponent = () => {
return <div>My Component</div>;
};
const LoggedMyComponent = withLogging(MyComponent);
const App = () => {
return (
<div>
<LoggedMyComponent />
</div>
);
};
export default App;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
2. 数据获取 HOC
这个高阶组件在组件挂载时从一个 API 获取数据,并将数据传递给被包装的组件。
FetchDataHOC.js
import React from 'react';
const withFetchData = (url) => (WrappedComponent) => {
return class extends React.Component {
state = {
data: null,
loading: true,
error: null,
};
async componentDidMount() {
try {
const response = await fetch(url);
const data = await response.json();
this.setState({ data, loading: false });
} catch (error) {
this.setState({ error, loading: false });
}
}
render() {
const { data, loading, error } = this.state;
return <WrappedComponent data={data} loading={loading} error={error} {...this.props} />;
}
};
};
export default withFetchData;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
使用数据获取 HOC
// src/App.js
import React from 'react';
import withFetchData from './FetchDataHOC';
const DataComponent = ({ data, loading, error }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>Data: {JSON.stringify(data)}</div>;
};
const FetchDataComponent = withFetchData('https://api.example.com/data')(DataComponent);
const App = () => {
return (
<div>
<FetchDataComponent />
</div>
);
};
export default App;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
3. 权限控制 HOC
这个高阶组件根据用户权限来控制组件的渲染。
withAuthorization.js
import React from 'react';
const withAuthorization = (requiredRole) => (WrappedComponent) => {
return class extends React.Component {
render() {
const { user } = this.props;
if (user.role !== requiredRole) {
return <div>You do not have permission to view this page</div>;
}
return <WrappedComponent {...this.props} />;
}
};
};
export default withAuthorization;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
使用权限控制 HOC
// src/App.js
import React from 'react';
import withAuthorization from './withAuthorization';
const AdminPage = () => {
return <div>Admin Page</div>;
};
const AuthorizedAdminPage = withAuthorization('admin')(AdminPage);
const App = () => {
const user = { role: 'user' }; // change to 'admin' to see the page
return (
<div>
<AuthorizedAdminPage user={user} />
</div>
);
};
export default App;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
4. 动态样式 HOC
这个高阶组件根据 props 动态添加样式。
withDynamicStyles.js
import React from 'react';
const withDynamicStyles = (WrappedComponent) => {
return class extends React.Component {
render() {
const style = {
color: this.props.color || 'black',
fontSize: this.props.fontSize || '16px',
};
return <WrappedComponent {...this.props} style={style} />;
}
};
};
export default withDynamicStyles;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
使用动态样式 HOC
// src/App.js
import React from 'react';
import withDynamicStyles from './withDynamicStyles';
const StyledComponent = ({ style }) => {
return <div style={style}>Styled Component</div>;
};
const DynamicStyledComponent = withDynamicStyles(StyledComponent);
const App = () => {
return (
<div>
<DynamicStyledComponent color="red" fontSize="20px" />
</div>
);
};
export default App;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.