React-query中mutation成功后跳转页面避免内存泄漏的方法
React-query Mutation后跳转页面的内存泄漏警告解决方法
出现这个警告的核心原因是:mutation异步操作完成后,当前组件已经被卸载,但回调里仍在尝试更新组件状态或执行后续操作。以下是几种实用的解决方式:
1. 通过isSuccess结合useEffect触发跳转
利用React-query提供的isSuccess状态,在组件挂载状态下执行跳转逻辑:
import { useMutation } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; const YourComponent = () => { const navigate = useNavigate(); const { mutate, isSuccess } = useMutation(yourMutationFunction); // 监听isSuccess状态,仅在组件挂载时执行跳转 useEffect(() => { if (isSuccess) { navigate('/target-page'); } }, [isSuccess, navigate]); const handleSubmit = () => { mutate(yourData); }; return <button onClick={handleSubmit}>提交</button>; };
2. 在onSuccess回调中检查组件挂载状态
用useRef跟踪组件是否挂载,避免卸载后执行状态更新或跳转:
import { useMutation } from '@tanstack/react-query'; import { useNavigate, useRef, useEffect } from 'react-router-dom'; const YourComponent = () => { const navigate = useNavigate(); const isMounted = useRef(true); const { mutate } = useMutation(yourMutationFunction, { onSuccess: () => { // 仅在组件挂载时执行后续操作 if (isMounted.current) { navigate('/target-page'); } } }); // 组件卸载时标记为未挂载 useEffect(() => { return () => { isMounted.current = false; }; }, []); const handleSubmit = () => { mutate(yourData); }; return <button onClick={handleSubmit}>提交</button>; };
3. 用mutateAsync结合挂载检查
如果习惯用async/await调用mutation,可结合挂载状态判断:
import { useMutation } from '@tanstack/react-query'; import { useNavigate, useRef, useEffect } from 'react-router-dom'; const YourComponent = () => { const navigate = useNavigate(); const isMounted = useRef(true); const { mutateAsync } = useMutation(yourMutationFunction); const handleSubmit = async () => { try { await mutateAsync(yourData); // 确认组件仍挂载再跳转 if (isMounted.current) { navigate('/target-page'); } } catch (err) { // 错误处理逻辑 } }; useEffect(() => { return () => { isMounted.current = false; }; }, []); return <button onClick={handleSubmit}>提交</button>; };
4. 取消未完成的异步请求(适用于可取消的请求)
如果你的mutation基于可取消的请求(比如Axios),可在组件卸载时主动取消:
import { useMutation } from '@tanstack/react-query'; import { useNavigate, useEffect } from 'react-router-dom'; import axios from 'axios'; const YourComponent = () => { const navigate = useNavigate(); const { mutate } = useMutation((data) => { const source = axios.CancelToken.source(); const request = axios.post('/api/your-endpoint', data, { cancelToken: source.token }); // 给请求附加取消方法 request.cancel = () => source.cancel('组件已卸载,取消请求'); return request; }, { onSuccess: () => navigate('/target-page') }); // 组件卸载时取消当前mutation请求 useEffect(() => { return () => { if (mutate.cancel) { mutate.cancel(); } }; }, [mutate]); const handleSubmit = () => { mutate(yourData); }; return <button onClick={handleSubmit}>提交</button>; };
内容的提问来源于stack exchange,提问作者Foyez
相关产品推荐
相关产品推荐

