目录
[1. 什么是 Hooks?为什么要用它?](#1. 什么是 Hooks?为什么要用它?)
[2. 基础 Hooks(日常开发使用率 90%)](#2. 基础 Hooks(日常开发使用率 90%))
[2.1 useState](#2.1 useState)
[2.2 useEffect](#2.2 useEffect)
[2.3 useContext](#2.3 useContext)
[3. 进阶 Hooks(性能优化与复杂逻辑)](#3. 进阶 Hooks(性能优化与复杂逻辑))
[3.1 useReducer](#3.1 useReducer)
[3.2 useCallback](#3.2 useCallback)
[3.3 useMemo](#3.3 useMemo)
[3.4 useRef](#3.4 useRef)
[4. 只有在特定场景才用的 Hooks](#4. 只有在特定场景才用的 Hooks)
[4.1 useLayoutEffect](#4.1 useLayoutEffect)
[4.2 useImperativeHandle](#4.2 useImperativeHandle)
[4.3 useDebugValue](#4.3 useDebugValue)
[5. React 18+ 新增 Hooks(并发模式相关)](#5. React 18+ 新增 Hooks(并发模式相关))
[5.1 useId](#5.1 useId)
[5.2 useTransition](#5.2 useTransition)
[5.3 useDeferredValue](#5.3 useDeferredValue)
[6. 自定义 Hook (Custom Hook)](#6. 自定义 Hook (Custom Hook))
重点总结
定义:Hooks 是 React 16.8 引入的,解决了 Class 组件逻辑复用难、this 指向混乱等问题,让函数组件拥有了状态和生命周期。
核心三剑客:重点介绍 useState(状态)、useEffect(副作用)、useContext(跨组件通信)。
性能优化:提到 useMemo(缓存值)和 useCallback(缓存函数),并说明它们是为了避免不必要的渲染和计算。
引用与操作:提到 useRef 用于访问 DOM 或存储不触发渲染的变量。
高阶场景:简单带过 useReducer(复杂状态)和 useLayoutEffect(同步 DOM 测量)。
React 18:如果想加分,提一下 useTransition 用于并发模式下的渲染优化。
1. 什么是 Hooks?为什么要用它?
定义:Hooks 是 React 16.8 引入的新特性,允许你在不编写 Class(类)组件的情况下,使用 State(状态)和其他 React 特性。
解决了什么问题(面试必问):
-
复用逻辑难:在 Class 组件中,复用逻辑通常依靠 HOC(高阶组件)或 Render Props,导致组件嵌套层级过深(Wrapper Hell)。Hooks 可以通过"自定义 Hook"完美解决。
-
组件复杂难以维护:Class 组件迫使我们将逻辑分散在 componentDidMount、componentDidUpdate 等生命周期中(例如:同一个定时器的启动和销毁被拆分)。Hooks 将相关逻辑聚合在一起。
-
Class 的 this 指向困扰:不需要再绑定 this。
两个铁律:
-
只能在函数组件的最顶层调用(不要在循环、条件或嵌套函数中调用)。
-
只能在 React 函数组件 或自定义 Hook 中调用。
2. 基础 Hooks(日常开发使用率 90%)
2.1 useState
-
作用:在函数组件中声明和管理状态。
-
API:const [state, setState] = useState(initialState);
-
场景:
- 简单的 UI 状态(如:模态框的显隐、输入框的值、计数器)。
-
面试考点:
-
setState 是异步的(批处理)。
-
如果新状态依赖于旧状态,推荐使用函数式更新:setCount(prev => prev + 1)。
-
2.2 useEffect
-
作用:处理副作用(Side Effects)。相当于 componentDidMount、componentDidUpdate 和 componentWillUnmount 的集合。
-
API:useEffect(setup, dependencies?)
-
场景:
-
数据获取(API 请求)。
-
订阅事件(如 addEventListener)。
-
手动修改 DOM(如 document.title)。
-
-
依赖项数组(重要):
-
\]:只在组件挂载时执行一次(类似 componentDidMount)。
-
不传:每次渲染都执行(慎用)。
-
-
清理函数:return 一个函数用于清除副作用(如清除定时器),类似 componentWillUnmount。
2.3 useContext
-
作用:接收 Context 对象,实现跨层级组件通信,避免"Props Drilling"(属性层层传递)。
-
API:const value = useContext(MyContext);
-
场景:
-
全局主题(Theme)。
-
用户登录状态(Auth)。
-
国际化配置(i18n)。
-
3. 进阶 Hooks(性能优化与复杂逻辑)
3.1 useReducer
-
作用:useState 的替代方案,用于管理复杂的状态逻辑。
-
API:const [state, dispatch] = useReducer(reducer, initialState);
-
场景:
-
状态逻辑复杂,包含多个子值(如表单对象)。
-
下一个状态依赖于之前的状态。
-
业务场景:购物车逻辑(添加、删除、更新数量)、复杂的表单验证。
-
-
理解:如果你用过 Redux,它就是 React 内置的迷你 Redux。
3.2 useCallback
-
作用 :缓存函数引用。
-
API:const memoizedCallback = useCallback(fn, dependencies);
-
场景:
- 将函数作为 props 传递给经过 React.memo 优化的子组件时,防止因父组件渲染导致函数引用变化,进而导致子组件不必要的重新渲染。
-
注意:不要滥用,只有在配合 React.memo 或作为其他 Hook 的依赖时才有意义。
3.3 useMemo
-
作用 :缓存计算结果。
-
API:const cachedValue = useMemo(calculateValue, dependencies);
-
场景:
-
昂贵的计算:例如处理大数组的过滤、排序。
-
避免在每次渲染时都进行高开销的计算。
-
-
区别:useCallback 缓存的是函数本身,useMemo 缓存的是函数的返回值。
3.4 useRef
-
作用:
-
访问 DOM 节点。
-
保存一个可变的变量,改变它不会触发组件重新渲染。
-
-
API:const refContainer = useRef(initialValue);
-
场景:
-
让输入框自动聚焦 (inputRef.current.focus())。
-
存储定时器的 ID(以便清理)。
-
记录上一次的 Props 或 State(实现 usePrevious)。
-
4. 只有在特定场景才用的 Hooks
4.1 useLayoutEffect
-
作用 :与 useEffect 类似,但它是在 DOM 变更之后、浏览器绘制之前 同步执行的。
-
场景:
-
你需要测量 DOM 元素的尺寸(如宽、高),并根据测量结果立即修改 DOM。
-
目的:防止页面闪烁(FOUC)。如果是为了读取布局信息,用它;如果是纯数据请求,用 useEffect。
-
4.2 useImperativeHandle
-
作用:自定义暴露给父组件的实例值(通常配合 forwardRef 使用)。
-
场景:
-
父组件需要调用子组件内部的方法(例如:父组件点击按钮,让子组件的 input 聚焦,或者重置子组件的表单)。
-
原则:尽量少用,React 推荐数据流驱动,而不是命令式调用。
-
4.3 useDebugValue
-
作用:在 React DevTools 中显示自定义 Hook 的标签。
-
场景:开发自定义 Hook 库时使用,方便调试。
5. React 18+ 新增 Hooks(并发模式相关)
5.1 useId
-
作用:生成唯一的 ID。
-
场景:
-
用于无障碍属性 aria-describedby。
-
服务端渲染(SSR)时,确保客户端和服务端生成的 ID 一致。
-
5.2 useTransition
-
作用:将某些状态更新标记为"不紧急"(Transition)。
-
API:const [isPending, startTransition] = useTransition();
-
场景:
- 输入框搜索:用户输入是紧急的(如果不响应会觉得卡),但下方的列表筛选渲染是不紧急的。可以用 startTransition 包裹列表的更新,保证输入框流畅。
5.3 useDeferredValue
-
作用:延迟更新某个值(类似防抖/节流,但由 React 自动控制)。
-
场景:
- 接收一个高频变化的值(如输入框的 value),返回一个延迟更新的版本,用于驱动耗时的列表渲染。
6. 自定义 Hook (Custom Hook)
这是 React Hooks 最强大的地方。
-
定义:就是一个普通的函数,但名字必须以 use 开头,且内部调用了其他 Hooks。
-
作用:提取组件逻辑,实现复用。
-
示例:
javascript// 封装一个获取窗口大小的 Hook function useWindowSize() { const [size, setSize] = useState([window.innerWidth, window.innerHeight]); useEffect(() => { const handleResize = () => setSize([window.innerWidth, window.innerHeight]); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return size; }