
react 开发模式下启用 strict mode 会导致 useeffect 模拟卸载/重挂载,从而执行两次;这是设计行为而非 bug,旨在帮助发现副作用清理问题。生产构建中不会出现此现象。
在 React(尤其是使用 App Router 的 Next.js 13+)中,你观察到 useEffect “执行两次”——例如倒计时结束时的清理逻辑被连续打印两次日志——这通常并非代码逻辑错误,而是 Strict Mode 的预期行为。
Strict Mode 是 React 提供的开发辅助工具,它会在开发环境(npm run dev)中对组件进行双渲染(double-invocation):即先挂载、渲染、执行副作用,再立即模拟卸载并重新挂载、渲染、再次执行副作用。其核心目标是提前暴露未正确清理的副作用(如未清除的定时器、未解绑的事件监听器、未取消的网络请求等)。
在你的倒计时示例中:
useEffect(() => {
if (timer < 1 && timer != null) {
setTimer(null);
clearInterval(intervalId.current);
console.log("proccccccccccccc"); // 这里被打印两次
}
}, [timer]);当 timer 降为 0 时,该 effect 触发。由于 Strict Mode 的双渲染机制,React 会:
- 第一次执行:检测到 timer
- 立即模拟卸载 → timer 变为 null(状态更新后);
- 再次挂载并执行 effect → 此时 timer 是 null,但 null 本应不执行。
⚠️ 但你加了 && timer != null 后反而“触发两次”,真实原因在于:null (因为 null 被强制转为 0,0 更根本的修复方式不是删条件,而是正确建模倒计时生命周期: ✅ 推荐写法(健壮、可读、规避 Strict Mode 干扰): ? 关键改进点: ? 补充说明: 遵循上述模式,你不仅能解决“执行两次”的困惑,更能写出符合 React 最佳实践、具备可维护性与鲁棒性的副作用逻辑。'use client';
import { useState, useEffect, useRef } from 'react';
export default function Home() {
const [timer, setTimer] = useState









