React.memo vs useMemo
React.memo vs useMemo
一句话:React.memo 是 「组件」级的 —— 决定要不要重新渲染整个组件;useMemo 是 「值」级的 —— 决定要不要重新计算一个值。
React.memo | useMemo | |
|---|---|---|
| 是什么 | 高阶组件 | hook |
| 用在哪 | 包在组件外面 | 写在组件里面 |
| 比较什么 | props(浅比较) | 依赖数组 |
| 省掉什么 | 一次组件渲染 | 一次计算 |
关键:三个必须配套用。只在子组件上加 React.memo通常一点效果都没有—— 因为父组件每次渲染都会给出新的对象和函数字面量, 浅比较必然判定「变了」。必须同时用useMemo 稳住对象、useCallback 稳住函数。
会追问:「memo 能拦住 context 变化吗?」——拦不住。memo 只比 props, context 走另一条通道。所以 context value 必须useMemo—— 这正是我们那道主题切换变式题的核心考点, 删掉 useMemo 后实测「功能测试全绿、 只有引用稳定性那条红」。
「children 会破坏 memo 吗?」—— 会,children 也是 prop, 而 JSX 每次都产生新元素对象。
In one line: React.memo works at the “component” level — it decides whether to re-render a whole component; useMemo works at the “value” level — it decides whether to recompute one value.
React.memo | useMemo | |
|---|---|---|
| What it is | A higher-order component | A hook |
| Where it goes | Wrapped around the component | Inside the component |
| What it compares | props (shallow) | the dependency array |
| What it saves | one component render | one computation |
The key point: all three go together. Dropping React.memo on a child usually does nothing at all — the parent hands down fresh object and function literals on every render, so the shallow compare is bound to say “changed”. You must also stabilise objects with useMemo and functions with useCallback.
Follow-up: “Can memo stop a context change?” — no it cannot. memo only compares props; context travels a separate channel. That is why a context value has to be wrapped in useMemo — exactly the point of our theme switching variant, where deleting the useMemo left every behaviour test green and only the reference-stability test red.
“Does children break memo?” — yes. children is a prop too, and JSX produces a new element object every time.