在 React 中,常用的高阶组件(HOC)模式包括增强组件功能、复用逻辑等。它们是接受一个组件并返回一个新组件的函数。高阶组件让我们在不修改原始组件的情况下,扩展组件功能。以下是几个常见的高阶组件的示例:
1. withLoading
(加载状态)
withLoading
用于在组件加载数据时显示一个加载指示器。
示例:
javascript
import React, { useState, useEffect } from 'react';
const withLoading = (fetchData) => (WrappedComponent) => {
return (props) => {
const [state, setState] = useState({ loading: true, data: null, error: null });
useEffect(() => {
fetchData()
.then(data => setState({ loading: false, data }))
.catch(error => setState({ loading: false, error }));
}, [fetchData]);
if (state.loading) return <div>加载中...</div>;
if (state.error) return <div>加载失败</div>;
return <WrappedComponent {...props} data={state.data} />;
};
};
export default withLoading;
使用:
javascript
import React from 'react';
import withLoading from './withLoading';
const fetchUserData = ({ data }) => fetch('/api/user').then(res => res.json());
const UserProfile = () => <div>姓名:{data.name}</div>;
export default withLoading(fetchUserData)(UserProfile);
2. withErrorBoundary
(错误边界)
withErrorBoundary
用于捕获组件渲染过程中的错误,并显示错误信息。
示例:
javascript
import React, { Component } from 'react';
const withErrorBoundary = (WrappedComponent) => {
return class extends Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
return this.state.hasError ? <div>出了点问题!</div> : <WrappedComponent {...this.props} />;
}
};
};
export default withErrorBoundary;
使用:
javascript
import React, { useState, useEffect } from 'react';
import withErrorBoundary from './withErrorBoundary';
const fetchUserData = () => fetch('/api/user').then(res => res.json());
const UserProfile = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetchUserData().then(setData).catch(console.error);
}, []);
return data ? <h1>{data.name}</h1> : '加载失败';
};
export default withErrorBoundary(UserProfile);
3. withAuth
(权限控制)
withAuth
用于检查用户是否登录或有权限访问某个页面。
示例:
javascript
import React, { useState, useEffect } from 'react';
import { Redirect } from 'react-router-dom';
const checkAuthStatus = () => fetch('/api/check-auth').then(res => res.json());
const withAuth = (WrappedComponent) => {
return (props) => {
const [isAuthenticated, setIsAuthenticated] = useState(null);
useEffect(() => { checkAuthStatus().then(setIsAuthenticated); }, []);
if (isAuthenticated === null) return <div>验证中...</div>;
if (!isAuthenticated) return <Redirect to="/login" />;
return <WrappedComponent {...props} />;
};
};
export default withAuth;
使用:
javascript
import React from 'react';
import withAuth from './withAuth';
const Dashboard = () => <div>欢迎来到仪表盘</div>;
export default withAuth(Dashboard);
4. withTheme
(主题支持)
withTheme
用于为组件提供主题样式或样式变量。
示例:
javascript
import React from 'react';
const withTheme = (WrappedComponent) => {
return (props) => {
const theme = { backgroundColor: 'lightblue', color: 'darkblue' };
return <div style={theme}><WrappedComponent {...props} /></div>;
};
};
export default withTheme;
使用:
javascript
import React from 'react';
import withTheme from './withTheme';
const ThemedComponent = () => <div>这是一个主题组件!</div>;
export default withTheme(ThemedComponent);
5. withWindowSize
(窗口尺寸)
withWindowSize
用于获取并传递当前窗口的尺寸信息。
示例:
javascript
import React, { useState, useEffect } from 'react';
const getWindowSize = () => ({ width: window.innerWidth, height: window.innerHeight });
const withWindowSize = (WrappedComponent) => {
return (props) => {
const [size, setSize] = useState(getWindowSize());
useEffect(() => {
const handleResize = () => setSize(getWindowSize());
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return <WrappedComponent {...props} windowSize={size} />;
};
};
export default withWindowSize;
使用:
javascript
import React from 'react';
import withWindowSize from './withWindowSize';
const ResponsiveNavbar = ({ windowSize }) => {
const isMobile = windowSize.width < 600;
return (
<nav style={{ backgroundColor: isMobile ? 'lightblue' : 'darkblue' }}>
<p>{isMobile ? '移动端导航' : '桌面端导航'}</p>
</nav>
);
};
export default withWindowSize(ResponsiveNavbar);
6. withRouter
(React Router)
withRouter
是 React Router 提供的 HOC,使组件能够访问路由信息(如路径、历史记录、路由参数等)。
示例:
javascript
import React from 'react';
import { withRouter } from 'react-router-dom';
const FormPage = ({ location, history }) => (
);
const FormPage = ({ location, history }) => (
<div>
<p>当前路径: {location.pathname}</p>
<button onClick={() => history.push('/new-path')}>跳转</button>
</div>
);
export default withRouter(FormPage);
7. connect
(Redux)
connect
是 react-redux
提供的,用于将 Redux 的 state 和 actions 绑定到组件的 props。
示例:
javascript
import React from 'react';
import { connect } from 'react-redux';
import { increment } from './actions';
const Cart = ({ cart, increment }) => (
<div>
{cart.map(item => (
<li key={item.id}>
{item.name} - {item.quantity}
<button onClick={() => increment(item.id)}>增加</button>
</li>
))}
</div>
);
const mapStateToProps = (state) => ({ cart: state.cart });
const mapDispatchToProps = { increment };
export default connect(mapStateToProps, mapDispatchToProps)(Cart);
总结
高阶组件(HOC)在 React 中提供了一种灵活的方式来复用逻辑并增强组件功能,提升代码复用性和可维护性。以下是常见的 HOC 示例:
withLoading
:显示加载状态。withErrorBoundary
:捕获渲染错误。withAuth
:实现权限控制。withTheme
:提供主题样式。withWindowSize
:获取窗口尺寸。withRouter
:访问路由信息。connect
:连接 Redux 状态和 actions。