如何在组件卸载时避免触发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
相关产品推荐
相关产品推荐

