React Hooks 最佳实践
引言
React Hooks 自 16.8 版本引入以来,彻底改变了我们编写 React 组件的方式。本文将分享一些在实际项目中总结的 Hooks 最佳实践。
useState 使用技巧
1. 状态更新函数
当新状态依赖于旧状态时,应该使用函数式更新:
// ❌ 不推荐
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
// ✅ 推荐
const increment = () => {
setCount(prevCount => prevCount + 1);
};
2. 对象状态更新
更新对象状态时需要手动合并:
const [user, setUser] = useState({ name: '', age: 0 });
// ❌ 会丢失其他属性
setUser({ name: 'August' });
// ✅ 正确方式
setUser(prev => ({ ...prev, name: 'August' }));
useEffect 注意事项
1. 依赖数组
始终指定正确的依赖数组,避免遗漏:
// ❌ 可能获取到过期的值
useEffect(() => {
fetchData(userId);
}, []);
// ✅ 正确指定依赖
useEffect(() => {
fetchData(userId);
}, [userId]);
2. 清理副作用
记得清理定时器、订阅等副作用:
useEffect(() => {
const timer = setInterval(() => {
// 执行任务
}, 1000);
return () => clearInterval(timer);
}, []);
自定义 Hooks
提取可复用的逻辑到自定义 Hooks:
// useLocalStorage.js
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
const setValue = (value) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
// 使用
const [theme, setTheme] = useLocalStorage('theme', 'light');
useMemo 和 useCallback
1. useMemo 用于计算缓存
// 避免重复计算
const filteredList = useMemo(() => {
return list.filter(item => item.active);
}, [list]);
2. useCallback 用于函数引用
// 避免子组件不必要的重渲染
const handleClick = useCallback(() => {
// 处理点击
}, [dependency]);
常见陷阱
- 过度优化:不要过早使用 useMemo/useCallback,只在性能瓶颈时使用
- 忽略依赖数组:可能导致闭包陷阱,获取到过期的值
- 在条件语句中使用 Hooks:Hooks 必须在顶层调用
- 滥用 useContext:全局状态过多会导致组件难以维护
总结
合理使用 Hooks 可以让代码更简洁、更易维护。关键是要理解每个 Hook 的工作原理和使用场景,避免常见陷阱。