You need to enable JavaScript to run this app. React简单useReducer应用中alert弹窗出现两次是什么原因?
优惠活动
大模型
产品
解决方案
定价
更多

React简单useReducer应用中alert弹窗出现两次是什么原因?

问题根因

你遇到的alert弹窗触发两次是两个问题叠加导致的:

  • 违反了useReducer要求reducer为纯函数的规范:reducer必须是无副作用的纯函数,不能直接编写alert、修改外部变量、发起请求这类副作用逻辑。
  • React 18 开发环境严格模式的校验机制:默认开启的严格模式下,React会在开发环境故意重复调用reducer、函数组件体等应该是纯函数的逻辑,用来提前发现不符合纯函数要求的隐藏问题,你的alert属于副作用逻辑,就会跟着重复执行。

当你把数值从1下调到0时,payload的value触发了alert分支,严格模式下reducer被调用两次,自然就弹出两次alert。生产环境下严格模式不会生效,这种写法下alert只会弹一次,但依然不符合React的设计规范,可能会引发其他隐藏问题。

修复方案

把副作用逻辑从reducer中剥离,放到useEffect或者事件回调中执行即可,修改后的参考代码如下:

import "./styles.css";
import { useReducer, useEffect } from "react";
const reducerFunction = (state, action) => {
  switch (action.type) {
    case "testing": {
      if (action.payload.value > 0) {
        return { ...state, testing: action.payload.value, showAlert: false };
      } else {
        // 仅标记需要触发提示,不执行副作用
        return { ...state, showAlert: true };
      }
    }
    default: {
      throw new Error("Invalid Action");
    }
  }
};
export default function App() {
  const defaultValue = {
    testing: 0,
    showAlert: false
  };
  const [state, dispatch] = useReducer(reducerFunction, defaultValue);

  // 副作用统一放到useEffect中执行
  useEffect(() => {
    if (state.showAlert) {
      alert("some message");
      // 触发后重置alert标记
      dispatch({ type: "testing", payload: { value: 0 } });
    }
  }, [state.showAlert, dispatch])

  return (
    <input
      value={state.testing}
      onChange={(e) => {
        // 建议先转成数字,避免字符串和数字比较的隐式转换问题
        const value = Number(e.target.value)
        dispatch({ type: "testing", payload: { value } });
      }}
      type="number"
    />
  );
}

内容的提问来源于stack exchange,提问作者Shishir Tiwari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 08:36:03