React Hooks 的优势和使用场景
1. Hooks 的核心优势
1.1 逻辑复用更简单
传统高阶组件(HOC)和render props会导致组件树嵌套过深,而Hooks可以通过自定义Hook实现逻辑复用:
jsx
代码解读
复制代码
// 自定义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 ComponentA() { const size = useWindowSize(); // ... } function ComponentB() { const size = useWindowSize(); // ... }
1.2 解决class组件痛点
- 避免this绑定问题
- 生命周期逻辑分散问题
- 更好的TS类型推断
1.3 代码更简洁
相同功能下,Hooks版本通常比class组件少30%代码量:
jsx
代码解读
复制代码
// Class组件 class Counter extends React.Component { state = { count: 0 }; componentDidMount() { document.title = `Count: ${this.state.count}`; } componentDidUpdate() { document.title = `Count: ${this.state.count}`; } render() { return ( <button onClick={() => this.setState({ count: this.state.count + 1 })}> Count: {this.state.count} </button> ); } } // Hooks版本 function Counter() { const [count, setCount] = useState(0); useEffect(() => { document.title = `Count: ${count}`; }, [count]); return ( <button onClick={() => setCount(count + 1)}> Count: {count} </button> ); }
2. 常用Hooks使用场景
2.1 useState - 状态管理
适用场景:
- 组件内部状态
- 表单控件状态
- 简单的UI状态切换
jsx
代码解读
复制代码
function Form() { const [name, setName] = useState(''); const [age, setAge] = useState(18); return ( <form> <input value={name} onChange={e => setName(e.target.value)} /> <input type="number" value={age} onChange={e => setAge(Number(e.target.value))} /> </form> ); }
2.2 useEffect - 副作用处理
适用场景:
- 数据获取
- 订阅事件
- 手动DOM操作
- 定时器管理
jsx
代码解读
复制代码
function DataFetcher({ id }) { const [data, setData] = useState(null); useEffect(() => { let isMounted = true; const fetchData = async () => { const result = await fetch(`/api/data/${id}`); if (isMounted) setData(await result.json()); }; fetchData(); return () => { isMounted = false; // 清理操作 }; }, [id]); // 依赖数组 return <div>{JSON.stringify(data)}</div>; }
2.3 useContext - 跨组件共享状态
适用场景:
- 主题切换
- 用户认证信息
- 多语言国际化
jsx
代码解读
复制代码
const ThemeContext = React.createContext('light'); function App() { return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar() { const theme = useContext(ThemeContext); return <div style={{ background: theme === 'dark' ? '#333' : '#fff' }} />; }
2.4 useReducer - 复杂状态逻辑
适用场景:
- 状态逻辑复杂
- 包含多个子值
- 下一个状态依赖前一个状态
jsx
代码解读
复制代码
function todosReducer(state, action) { switch (action.type) { case 'add': return [...state, { text: action.text, completed: false }]; case 'toggle': return state.map((todo, i) => i === action.index ? {...todo, completed: !todo.completed} : todo ); default: return state; } } function TodoList() { const [todos, dispatch] = useReducer(todosReducer, []); return ( <div> {todos.map((todo, i) => ( <div key={i} onClick={() => dispatch({ type: 'toggle', index: i })}> {todo.text} </div> ))} <button onClick={() => dispatch({ type: 'add', text: 'New todo' })}> Add Todo </button> </div> ); }
2.5 useMemo/useCallback - 性能优化
适用场景:
- 计算昂贵的值
- 避免不必要的子组件重渲染
- 稳定的回调引用
jsx
代码解读
复制代码
function ExpensiveComponent({ list, filter }) { const filteredList = useMemo(() => { return list.filter(item => item.includes(filter)); }, [list, filter]); // 只有依赖变化时重新计算 const handleClick = useCallback(() => { console.log('Clicked with filter:', filter); }, [filter]); // 保持稳定的函数引用 return ( <div> {filteredList.map(item => ( <div key={item} onClick={handleClick}>{item}</div> ))} </div> ); }
3. 最佳实践
-
Hooks调用规则
- 只在React函数组件或自定义Hook中调用
- 只在最顶层调用,不能在条件、循环或嵌套函数中调用
-
依赖数组优化
- useEffect/useMemo/useCallback的依赖数组要完整
- 使用eslint-plugin-react-hooks检查依赖
-
自定义Hook封装
- 以use开头的命名约定
- 可以组合多个基础Hook
-
性能考量
- 避免在渲染函数中进行昂贵计算
- 合理使用useMemo/useCallback
- 大型列表使用虚拟滚动
-
测试策略
- 使用@testing-library/react-hooks测试自定义Hook
- 注意异步effect的测试
4. 总结
React Hooks通过函数式的方式简化了状态管理和副作用处理,主要优势包括:
- 更简洁的代码结构
- 更好的逻辑复用
- 更直观的组件编写方式
- 更友好的TypeScript支持
典型使用场景包括:
- 组件状态管理(useState)
- 副作用处理(useEffect)
- 上下文共享(useContext)
- 复杂状态逻辑(useReducer)
- 性能优化(useMemo/useCallback)
随着React 18的并发特性推出,Hooks将成为未来React开发的标准模式。建议新项目全面采用Hooks,老项目可以逐步迁移。
链接:https://juejin.cn/post/7496397558359113782