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

如何在组件卸载时避免触发Toast?(提交表单时不触发)

问题解决思路

你的代码问题出在useState的异步更新特性:在onSubmit中调用setFormSubmitted(true)后立刻执行navigate,组件会马上卸载,但此时formSubmitted的状态还没完成更新,导致useEffect的清理函数里读取到的依然是旧值false,所以Toast还是会触发。

改用useRef就能解决这个问题,因为ref的更新是同步的,组件卸载时能拿到最新的标记值:

import { useRef } from 'react';
import { useFormik } from 'formik';
import { toast } from '@chakra-ui/react';
import { useNavigate } from 'react-router-dom';

// ...其他组件代码

const formSubmittedRef = useRef(false);
const navigate = useNavigate();

const formik = useFormik({
  onSubmit: async (values) => {
    formSubmittedRef.current = true; // 同步更新提交标记
    // 保留你的表单提交逻辑
    await yourSubmitApiCall(values);
    navigate('/toAnotherPage');
  }
});

useEffect(() => {
  return () => {
    // 仅当表单已修改且未提交时触发Toast
    if (formik.dirty && !formSubmittedRef.current) {
      toast({
        description: "Save info to draft",
        status: "success",
        duration: 3000,
        isClosable: false,
        containerStyle: {
          fontSize: "16px",
          fontWeight: "350",
        },
      });
    }
  };
}, [formik.dirty]); // 依赖仅保留formik.dirty,ref无需加入依赖

关键说明

  • useRef的current属性是同步更新的,不会像useState那样存在异步延迟,组件卸载前能准确获取提交状态。
  • 清理函数的依赖项不需要包含formSubmittedRef,因为ref的变化不会触发组件重渲染,我们直接读取的是它的最新current值。
  • 如果你的提交逻辑是异步操作(比如调用后端接口),确保在异步操作完成后再执行跳转,避免未完成提交就卸载组件的异常情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:34:53