You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

渲染SweetAlert时出现React已渲染状态下无法刷新更新警告如何解决

报错原因

这个unstable_flushDiscreteUpdates警告的本质是React执行渲染流程的同时,有其他同步状态更新被触发,导致React无法正常处理离散更新队列,你的代码存在3个直接诱因:

  • Formik的render props回调参数和外层LoginOverlay的入参都命名为props,造成作用域污染,同时SweetAlert的html属性直接读取Formik的实时values,Formik状态更新触发重渲染时如果刚好切换SweetAlert的显隐状态,会同步触发SweetAlert内部的DOM/状态更新,和当前渲染流程冲突
  • 同步重定向逻辑直接写在JSX返回中,<Redirect>组件渲染时会同步触发路由状态更新,此时如果刚好SweetAlert也在切换显隐,就会触发更新嵌套
  • 两个SweetAlert组件都放在Formik的render回调内部,Formik的任意状态变化都会触发这两个组件的props重新计算,旧版本的SweetAlert React封装库内部状态更新没有用副作用包装,会直接在渲染阶段触发更新

解决方案

按顺序执行以下修改即可:

  1. 修复命名冲突,避免作用域污染
    把Formik的render props回调参数改名,所有Formik内部属性用新名称调用:
// 原代码
{(props) => (
// 修改为
{(formikProps) => (
// 后续所有Formik属性调用同步改为formikProps.xxx,比如formikProps.getFieldProps、formikProps.values.email
  1. 把重定向逻辑移到副作用中,避免渲染时同步触发路由更新
    新增useEffect处理重定向,删除原有JSX中的<Redirect>代码段:
useEffect(() => {
  if (localStorage.getItem("did_token") || magic.entity?.loggedIn) {
    history.push('/business/home')
  }
}, [magic.entity?.loggedIn, history])
  1. 把SweetAlert组件移出Formik的render回调
    将两个SweetAlert放到LoginOverlay的根返回节点下,减少不必要的重渲染触发,修改后代码结构如下:
const LoginOverlay = (props) => {
  const history = useHistory();
  const { magic, login, clearError } = props;

  // 新增的重定向逻辑
  useEffect(() => {
    if (localStorage.getItem("did_token") || magic.entity?.loggedIn) {
      history.push('/business/home')
    }
  }, [magic.entity?.loggedIn, history])

  return (
    <>
      <Formik
        // 原有Formik配置保持不变
        {(formikProps) => (
          <div className="app-wrapper min-vh-100 bg-white">
            {/* 原有布局、表单代码全部保持不变,删除里面的SweetAlert、Redirect代码段 */}
          </div>
        )}
      </Formik>
      {/* 两个SweetAlert移到此处 */}
      <SweetAlert
        title="Check your email"
        show={!magic.entity?.loggedIn && magic.showInfoDialog}
        html={`We emailed a magic link to ${formikProps.values.email}</br>Click the link in your email and then return to this tab to log in or sign up.</br>`}
        type="info"
        showCancelButton={false}
        showConfirmButton={false}
      />
      <SweetAlert
        title="Error"
        show={!magic.entity?.loggedIn && magic.errorMessage}
        html={magic.errorMessage}
        type="error"
        showCancelButton={false}
        showConfirmButton={true}
        onConfirm={() => clearError()}
      />
    </>
  )
}
  1. 若修改后仍有警告,给SweetAlert的显隐状态加微任务延迟,避免和父组件渲染同步
    新增state控制SweetAlert显隐,用useEffect + 0延迟定时器更新状态,把更新操作放到下一个事件循环执行:
const [showInfoAlert, setShowInfoAlert] = useState(false)
const [showErrorAlert, setShowErrorAlert] = useState(false)

useEffect(() => {
  setTimeout(() => {
    setShowInfoAlert(!magic.entity?.loggedIn && magic.showInfoDialog)
    setShowErrorAlert(!magic.entity?.loggedIn && !!magic.errorMessage)
  }, 0)
}, [magic.entity?.loggedIn, magic.showInfoDialog, magic.errorMessage])

再把SweetAlert的show属性替换为对应的state即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:24:06