useState
面试速答(30 秒版 TL;DR)
useState是 React 函数组件最基础的本地状态 Hook。- 它返回
[state, setState],当状态更新后,React 会调度组件重新渲染。 - React 18 下要重点记 3 个点:
- 状态更新是异步调度的,不要立刻假设读取到的是新值
- 多次更新可能会被 batching(批处理)
- 新值如果经
Object.is比较后认为没变,React 可以跳过无意义重渲染
- 面试不要只会背语法,更要说明:状态为什么会触发 render,以及闭包、批处理、函数式更新这些边界。
1. 基本用法
const [count, setCount] = useState(0)
含义很直接:
count:当前状态值setCount:发起更新
2. 为什么调用 setState 会重新渲染
因为 React 把 state 看成组件输出 UI 的输入之一。
当 state 变化时,React 需要重新执行组件函数,重新计算:
- JSX 长什么样
- 子组件传什么 props
- 哪些节点需要更新
所以“更新 state”本质上是在告诉 React:
这棵 UI 相关输入变了,请重新计算一遍。
3. React 18 下最重要的 3 个知识点
3.1 批处理更普遍了
React 18 里,很多异步场景下的多次更新也会自动批处理。
setA(1)
setB(2)
通常不会触发两次单独提交,而是合并处理,减少额外渲染。
3.2 闭包旧值
setCount(count + 1)
setCount(count + 1)
如果这里的 count 来自同一次 render,最终可能只加一次。
更稳的写法是函数式更新:
setCount(c => c + 1)
setCount(c => c + 1)
3.3 相同值优化
如果新旧值经比较后没变化,React 可能跳过无意义更新。
4. 惰性初始化
如果初始值计算比较重,可以传函数:
const [state] = useState(() => createInitialState())
这样只在首次初始化时执行一次。
5. useState 和 useReducer 怎么选
5.1 useState
更适合:
- 单值
- 简单对象
- 更新逻辑直接
5.2 useReducer
更适合:
- 多分支 action
- 状态转移复杂
- 需要统一收口更新逻辑
6. 面试高频答法
Q1:为什么 setState 后不能马上拿到新值?
因为它不是立即同步改变量,而是发起一次状态更新调度,真正的新值会在下一轮渲染里体现。
Q2:为什么推荐函数式更新?
因为它基于“上一个最新状态”计算,能避免闭包旧值问题,尤其适合:
- 连续多次更新
- 异步回调更新
Q3:React 18 的自动批处理有什么意义?
减少不必要的重复渲染,让多个相关状态更新能合并提交,提升性能和一致性。
常见追问
1)对象 state 更新为什么要返回新对象?
因为 React 依赖引用变化判断状态是否变化,直接改原对象容易让更新失效或难以追踪。
2)一个组件里可以有很多个 useState 吗?
可以。拆分多个 state 往往比一个大对象更清晰,前提是它们语义上确实独立。
易错点/坑
- 以为
setState是立即同步赋值。 - 连续
setCount(count + 1)却没意识到闭包问题。 - 直接修改对象/数组原值而不是返回新引用。
速记要点(可背诵)
useState:最基础的本地状态 Hook。- React 18 高频点:自动批处理、闭包旧值、函数式更新。
- 页面要变,就改 state;改 state,本质是在触发新一轮 UI 计算。