React Router v5搭配React Query导航时请求不取消不重发问题
不需要手动刷新组件,也不需要将请求放入useEffect钩子中,你的问题根源是react-query的使用方式不符合需求,加上少量代码笔误导致的。react-query的useQuery已经内置了请求触发、缓存管理、重发等能力,不需要额外用useEffect包裹请求。
问题根因
- 查询Key固定:react-query通过查询Key(useQuery第一个参数)区分不同请求、管理缓存,你当前用固定字符串
planeInfo作为Key,即便路由id变化,react-query也会复用之前的缓存数据,不会发起新请求。 - 没有配置请求取消:你当前的fetch请求没有绑定AbortSignal,react-query无法在组件卸载(导航离开时)自动终止未完成的请求。
- 代码笔误:定义的请求函数是
fetchChart,但useQuery中传的是不存在的fetchPlane;fetch请求中使用的id变量未定义,应该是路由参数alertInnerId;路由定义的路径是/details/:id,但跳转时用的是/detail/${id},路径不匹配。
解决方案
1. 修正Component2代码
import React from 'react'; import { useQuery } from 'react-query'; import { RouteComponentProps, useLocation } from "react-router-dom"; interface stateType { model: { pathname: string }, start: { pathname: string | Date } } // 明确指定路由参数类型 const Component2: React.FunctionComponent<RouteComponentProps<{id: string}>> = (props) => { const { state } = useLocation<stateType>(); const alertInnerId = props.match.params.id; // 接收react-query传入的signal,用于自动取消请求 const fetchChart = async ({ signal }) => { const res = await fetch(`/detail/${alertInnerId}`, { signal }); if (!res.ok) throw new Error('请求失败') return res.json(); }; // 把id加入查询Key,id变化时自动触发新请求 const { data, status } = useQuery(['planeInfo', alertInnerId], fetchChart, { staleTime: 5000, // 可选配置:每次挂载组件都强制重新请求,无视缓存新鲜度 // refetchOnMount: 'always' }); return ( <> {status === 'error' && ( <div className="mt-5">Error fetching data!</div> )} {status === 'loading' && ( <div className="mt-5">Loading data ...</div> )} {status === 'success' && ( data.map(inner => <p key={inner.id}>{inner.id}</p>) )} </> ) } export default Component2;
2. 修正路由路径不匹配问题
要么把路由配置里的path="/details/:id"改成path="/detail/:id",要么把Component1里的跳转路径改成/details/${id},保持路径一致即可。
修改后即可实现:路由id变化时自动发起新请求,导航离开组件时未完成的请求会被自动取消,符合你的需求。
内容的提问来源于stack exchange,提问作者Sole
相关产品推荐
相关产品推荐

