目录
1. 单元测试(Jest + Testing Library)
一、性能优化策略
1. 组件渲染优化
React.memo
:缓存函数组件,避免不必要的渲染(浅比较 props)
const MemoComponent = React.memo(function MyComponent({ data }) {
return <div>{data}</div>;
});
useMemo
:缓存计算结果
const expensiveValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback
:缓存回调函数
const handleClick = useCallback(() => {
console.log('Clicked:', id);
}, [id]);
2. 虚拟 DOM 优化
避免在渲染函数中进行高开销操作(如复杂计算、DOM 操作)
使用 key 属性稳定化(避免索引作为 key)
3. 代码分割(Lazy Loading)
React.lazy
+ Suspense
:动态加载组件
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
二、高级 Hooks 模式
1. 自定义 Hook
封装可复用的逻辑:
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}
// 使用
function App() {
const { data, loading } = useFetch('https://api.example.com/data');
// ...
}
2. useReducer
复杂状态管理
替代 useState 处理多层嵌套或关联状态:
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
);
}
3. useContext 深度使用
配合 状态管理库 或 主题/全局配置:
const UserContext = React.createContext();
function App() {
const [user, setUser] = useState({ name: 'John', id: 1 });
return (
<UserContext.Provider value={{ user, setUser }}>
<Profile />
</UserContext.Provider>
);
}
function Profile() {
const { user } = useContext(UserContext);
return <div>{user.name}</div>;
}
三、状态管理进阶
1. Redux Toolkit 现代 Redux 实践
安装:
npm install @reduxjs/toolkit react-redux
创建 Store:
// store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: state => { state.value += 1 },
decrement: state => { state.value -= 1 }
}
});
export const store = configureStore({
reducer: {
counter: counterSlice.reducer
}
});
export const { increment, decrement } = counterSlice.actions;
连接 React:
import { Provider, useSelector, useDispatch } from 'react-redux';
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
function Counter() {
const count = useSelector(state => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(decrement())}>-</button>
<span>{count}</span>
<button onClick={() => dispatch(increment())}>+</button>
</div>
);
}vvvvvvvv
2. 状态选择器优化
使用 Reselect 或 Redux Toolkit 的 createSelector
缓存派生数据:
import { createSelector } from '@reduxjs/toolkit';
const selectUser = state => state.user;
const selectPosts = state => state.posts;
const selectUserPosts = createSelector(
[selectUser, selectPosts],
(user, posts) => posts.filter(post => post.userId === user.id)
);
四、高级组件模式
1. Render Props
function MouseTracker({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleMouseMove = e => {
setPosition({ x: e.clientX, y: e.clientY });
};
return <div onMouseMove={handleMouseMove}>{render(position)}</div>;
}
// 使用
<MouseTracker render={({ x, y }) => (
<h1>Mouse position: {x}, {y}</h1>
)} />
2. 高阶组件 (HOC)
function withLogger(WrappedComponent) {
return function(props) {
useEffect(() => {
console.log('Component mounted:', WrappedComponent.name);
return () => console.log('Component unmounted:', WrappedComponent.name);
}, []);
return <WrappedComponent {...props} />;
};
}
const EnhancedComponent = withLogger(MyComponent);
3. 复合组件(Compound Components)
通过 Context 共享状态:
const TabsContext = React.createContext();
function Tabs({ children }) {
const [activeTab, setActiveTab] = useState(0);
return (
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
<div className="tabs">{children}</div>
</TabsContext.Provider>
);
}
function Tab({ index, children }) {
const { activeTab, setActiveTab } = useContext(TabsContext);
return (
<button
className={activeTab === index ? 'active' : ''}
onClick={() => setActiveTab(index)}
>
{children}
</button>
);
}
// 使用
<Tabs>
<Tab index={0}>Tab 1</Tab>
<Tab index={1}>Tab 2</Tab>
</Tabs>
五、错误边界与异步处理
1. 错误边界(Error Boundaries)
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
// 使用
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
2. Suspense 数据获取
(React 18+ 实验性功能)
// 实现一个简单的 Suspense 兼容的数据源
function fetchData(url) {
let status = 'pending';
let result;
let suspender = fetch(url)
.then(res => res.json())
.then(data => {
status = 'success';
result = data;
})
.catch(error => {
status = 'error';
result = error;
});
return {
read() {
if (status === 'pending') throw suspender;
if (status === 'error') throw result;
return result;
}
};
}
// 组件中使用
const dataResource = fetchData('/api/data');
function MyComponent() {
const data = dataResource.read();
return <div>{data.message}</div>;
}‘
六、TypeScript 集成
1. 组件 Props 类型定义
interface ButtonProps {
primary?: boolean;
size?: 'small' | 'medium' | 'large';
onClick?: () => void;
children: React.ReactNode;
}
const Button: React.FC<ButtonProps> = ({ primary, size, onClick, children }) => {
// ...
};
组件props类型检查
import PropTypes from 'prop-types';
function Button({ primary, size, onClick, children }) {
// ...
}
Button.propTypes = {
primary: PropTypes.bool,
size: PropTypes.oneOf(['small', 'medium', 'large']),
onClick: PropTypes.func,
children: PropTypes.node.isRequired
};
Button.defaultProps = {
primary: false,
size: 'medium'
};
2. 泛型组件
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return <div>{items.map(renderItem)}</div>;
}
// 使用
<List<{ id: number; name: string }>
items={users}
renderItem={user => <div key={user.id}>{user.name}</div>}
/>
七、测试策略
1. 单元测试(Jest + Testing Library)
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('increments counter', () => {
render(<Counter />);
const button = screen.getByText('+');
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
2. 端到端测试(Cypress)
describe('Login Flow', () => {
it('successfully logs in', () => {
cy.visit('/login');
cy.get('#email').type('user@example.com');
cy.get('#password').type('password123');
cy.get('button[type="submit"]').click();
cy.url().should('include', '/dashboard');
});
});
八、部署与优化
1. 生产环境构建
npm run build # 生成优化的静态文件到 build/ 目录
2. 性能分析
使用 React DevTools Profiler 分析组件渲染
通过 reportWebVitals
监控 Core Web Vitals
3. CDN 与缓存策略
静态资源添加哈希指纹(main.a3b4c5.js
)
配置长期缓存(Cache-Control: max-age=31536000)
九、进阶学习方向
服务端渲染:Next.js 深度使用
微前端架构:Module Federation
动画库:Framer Motion, React Spring
数据可视化:D3.js 集成
Web Workers:处理 CPU 密集型任务
十、推荐资源
通过实现复杂应用(如电商平台、实时聊天系统)并参与开源项目,持续提升 React 工程化能力!
码字不易,各位大佬点点赞呗