DrillLab
第 78 / 105 道78 / 105 · #332

什么是 StrictMode

What is React strict mode

先自己答,再往下看Answer it yourself first

一句话:一个只在开发模式生效的检查工具组件, 通过故意多做一次来暴露不安全的写法。生产构建里它什么都不做。

它做三件事:

  • 渲染函数调用两次—— 暴露渲染过程中的副作用 (改了外部变量、直接 mutate props)。因为 render 阶段可能被中断重跑 (见 #353),所以它必须是纯的。
  • React 18 起:effect 会 「挂载 → 卸载 → 再挂载」——专门暴露「没写清理函数」的 effect。 如果你的组件挂两次就出问题 (重复订阅、定时器翻倍), 那就是真 bug。
  • 警告废弃 API 和过时的 ref 写法。

最重要的一句: 「双重渲染导致的问题」不是 StrictMode 的问题, 是你的代码的问题。很多人第一反应是「关掉它」—— 正确反应是修好副作用。

会追问:「日志被打印两次正常吗?」—— 开发模式下正常,因为渲染函数被调了两次; 生产不会。
「请求被发两次呢?」——这个要认真看: 说明你的 effect 没有正确处理清理 —— 虽然对幂等的 GET 无害, 但它同时提示你「竞态防护写了没有」。我们那道 fetch 变式题里ignore 标志 +abort 的写法, 正好让它在 StrictMode 下也表现正确。

In one line: a checking component that only does anything in development, and it exposes unsafe code by deliberately doing things twice. In a production build it does nothing.

It does three things:

  • Calls your render function twice — which surfaces side effects during render (mutating an outer variable, mutating props directly). Because the render phase can be interrupted and re-run (see #353), it has to be pure.
  • Since React 18: effects run mount, unmount, mountspecifically to expose effects with no cleanup function. If mounting twice breaks your component (a duplicated subscription, a doubled timer), that is a real bug.
  • Warns about deprecated APIs and legacy ref patterns.

The most important sentence: a problem caused by double rendering is not StrictMode’s problem, it is your code’s. Most people’s first instinct is to turn it off — the right instinct is to fix the side effect.

Follow-up: “Is it normal for my log to print twice?” — yes in development, because the render function ran twice; it will not in production.
“What about my request firing twice?” — take that one seriously: it means your effect is not cleaning up properly. Harmless for an idempotent GET, but it is also telling you to ask whether you guarded against races. The ignore flag plus abort pattern from our fetch variant is exactly what makes it behave correctly under StrictMode too.