React Hooks 是 React 16.8 引入的重要特性,它彻底改变了 React 组件的编写方式。以下是 React Hooks 的核心优势和使用场景:
### 一、React Hooks 的核心优势
1. **简化组件逻辑**
- 告别 class 组件的繁琐写法
- 逻辑关注点分离更清晰
- 代码量减少 30%-50%
2. **更好的逻辑复用**
- 自定义 Hook 实现跨组件逻辑共享
- 告别高阶组件(HOC)的嵌套地狱
- 避免 Render Props 的组件冗余
3. **更直观的状态管理**
- useState 简化局部状态管理
- useReducer 处理复杂状态逻辑
- 状态与生命周期解耦
4. **性能优化更便捷**
- useMemo/useCallback 避免不必要的计算
- 细粒度的依赖项控制
- 减少不必要的重新渲染
5. **渐进式采用**
- 完全向后兼容
- 可与 class 组件并存
- 无需重写现有代码
### 二、核心 Hook 使用场景
1. **useState - 状态管理**
```jsx
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
点击次数: {count}
</button>
);
}
- useEffect - 副作用处理
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe(); // 清除副作用
};
}, [props.source]); // 依赖项数组
- useContext - 跨组件数据共享
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return <div style={{ background: theme }} />;
}
- useReducer - 复杂状态逻辑
function todosReducer(state, action) {
switch (action.type) {
case 'add':
return [...state, action.payload];
default:
return state;
}
}
function Todos() {
const [todos, dispatch] = useReducer(todosReducer, []);
return (
<button onClick={() => dispatch({ type: 'add', payload: '新任务' })}>
添加任务
</button>
);
}
- 自定义 Hook - 逻辑复用
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => setSize({
width: window.innerWidth,
height: window.innerHeight
});
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}
// 在任何组件中使用
function MyComponent() {
const { width } = useWindowSize();
return <div>窗口宽度: {width}px</div>;
}
三、最佳实践
-
Hook 使用规则
- 只在 React 函数组件顶层调用
- 不要在循环、条件或嵌套函数中调用
- 自定义 Hook 必须以 use 开头
-
性能优化技巧
- 合理使用依赖项数组
- 使用 useCallback 缓存函数
- 使用 useMemo 缓存计算结果
-
常见问题解决
- 无限循环: 检查 useEffect 依赖项
- 过时闭包: 使用函数式更新
- 内存泄漏: 正确清理副作用
-
与 Class 组件的对比
- componentDidMount → useEffect(fn, [])
- componentDidUpdate → useEffect(fn)
- componentWillUnmount → useEffect(() => fn, [])
- this.state → useState/useReducer
四、高级应用场景
- 表单处理
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = (e) => {
const { name, value } = e.target;
setValues(prev => ({ ...prev, [name]: value }));
};
return [values, handleChange];
}
- 动画效果
function useAnimation(duration) {
const [progress, setProgress] = useState(0);
useEffect(() => {
const start = Date.now();
const frame = () => {
const elapsed = Date.now() - start;
setProgress(Math.min(elapsed / duration, 1));
if (elapsed < duration) requestAnimationFrame(frame);
};
requestAnimationFrame(frame);
}, [duration]);
return progress;
}
- 数据请求
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const response = await fetch(url);
const result = await response.json();
setData(result);
setLoading(false);
};
fetchData();
}, [url]);
return { data, loading };
}
React Hooks 通过提供更简洁的 API 和更强大的抽象能力,显著提升了 React 的开发体验。随着 React 生态的不断发展,Hooks 已成为现代 React 开发的标准实践。