一、Hooks的诞生背景(Why Hooks?)
-
类组件的痛点
- 状态逻辑难以复用(render props/HOC导致嵌套地狱)
- 生命周期割裂逻辑(如
componentDidMount和componentDidUpdate中重复代码) this指向问题和类对编译优化的阻碍
-
函数组件的局限
- 无状态、无生命周期能力(Hooks出现前的函数组件仅适合展示型组件)
// 类组件状态管理 VS 函数组件+Hooks
class Counter extends React.Component {
state = { count: 0 };
handleClick = () => this.setState({ count: this.state.count + 1 });
render() { return <button onClick={this.handleClick}>{this.state.count}</button> }
}
// 使用Hooks的函数组件
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c+1)}>{count}</button>;
}
二、核心Hooks原理解析
-
useState- 状态管理- 闭包存储原理:通过闭包保存状态,依赖调用顺序保证状态对应
- 异步批量更新:多状态变更合并渲染,可用函数式更新保证准确性
const [state, setState] = useState(initialState); setState(prev => prev + 1); // 函数式更新解决闭包陷阱 -
useEffect- 副作用管理- 执行时机:DOM更新后异步执行(
useLayoutEffect同步执行) - 依赖数组控制:空数组=挂载/卸载时执行,省略=每次渲染执行
useEffect(() => { const subscription = props.source.subscribe(); return () => subscription.unsubscribe(); // 清理函数 }, [props.source]); // 依赖项变化时重新订阅 - 执行时机:DOM更新后异步执行(
-
useRef- 持久化引用- 跨渲染周期保存值(不触发重渲染)
- 访问DOM节点的官方方式
const inputRef = useRef(); useEffect(() => { inputRef.current.focus() }, []); return <input ref={inputRef} />;
三、进阶Hooks应用场景
-
性能优化三剑客
useMemo:缓存计算结果useCallback:缓存回调函数React.memo:组件浅比较缓存
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]); -
全局状态管理
-
useContext+useReducer实现轻量Redux
const ThemeContext = createContext('light'); function App() { return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar() { const theme = useContext(ThemeContext); // 读取当前主题 } -
-
自定义Hook实现逻辑复用
- 提取公共逻辑(如监听窗口大小、表单处理)
function useWindowWidth() { const [width, setWidth] = useState(window.innerWidth); useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return width; } // 使用自定义Hook const width = useWindowWidth();
四、Hooks实战最佳实践
-
遵循官方规则
- 只在函数组件顶层调用Hooks(不在循环/条件中)
- 自定义Hook必须以
use开头(便于ESLint规则检查)
-
调试与性能分析
- 使用React DevTools的Hooks调试功能
- 通过
<Profiler>组件测量渲染性能
-
测试策略
- 使用
@testing-library/react-hooks单独测试自定义Hooks
test('should use custom hook', () => { const { result } = renderHook(() => useCounter()) act(() => result.current.increment()) expect(result.current.count).toBe(1) }) - 使用
五、Hooks生态与未来趋势
-
主流库的Hooks适配
- React Router:
useParams,useNavigate - Redux:
useSelector,useDispatch - SWR/React Query:
useSWR,useQuery
- React Router:
-
Server Components新范式
- 服务端组件与客户端组件的Hooks使用差异
- Streaming SSR与Hooks的结合