React useHistory Hook跳转未触发重渲染、数据不更新问题求助
问题根源
- 异步请求未完成就跳转:EditBanner组件的PUT更新请求是异步操作,你没有等待请求返回成功就直接调用history.push跳转到详情页,此时后端数据还没完成更新,详情页请求到的自然是旧数据。
- 同id路由跳转时useEffect未触发:你从
/banners/:id/edit跳转到/banners/:id时,路由参数id没有变化,useParams返回的params对象引用未更新,BannerDetail组件的useEffect依赖params不会重新执行,也就不会拉取最新数据。
解决方案
第一步:修改EditBanner的提交逻辑,等待更新请求完成再跳转
将onSubmitHandler改为异步函数,await PUT请求执行完成后再执行跳转操作,确保跳转时后端数据已经是最新的:
// EditBanner组件的onSubmitHandler修改如下 const onSubmitHandler = async (e) => { e.preventDefault() // 等待PUT请求完成 await fetch(`URL/banners/${params.id}.json`,{ method: "PUT", body: JSON.stringify({ description: descriptionRef.current.value, img: imgRef.current.value }), headers: { 'Content-Type': 'application/json' } }) // 请求成功后再跳转 history.push(`/banners/${params.id}`); }
第二步:修改BannerDetail的useEffect依赖,确保路径变化时重新拉取数据
导入useLocation钩子,将路径作为依赖项加入useEffect,只要页面路径发生变化(哪怕id相同)就会重新请求最新数据:
// 先导入useLocation import { useParams, useHistory, useLocation } from 'react-router'; const BannerDetail = (props) => { const history = useHistory(); const params = useParams(); const location = useLocation(); // 新增 const [bannerDetail, setBannerDetail] = useState({}); useEffect(() => { const fetchBanner = async () => { const response = await fetch(`URL/banners/${params.id}.json`); const data = await response.json(); setBannerDetail(data); } fetchBanner(); // 依赖增加location.pathname,同时把params改为params.id优化依赖稳定性 },[params.id, location.pathname]) // 其余代码不变 }
注:把params改成params.id是优化依赖,避免params引用变化导致不必要的请求,用基础类型的id作为依赖更稳定,也不会出现你提到的无限循环问题。
可选补充:请求增加错误捕获
可以给异步请求加try/catch处理异常情况,避免更新失败还跳转的问题:
const onSubmitHandler = async (e) => { e.preventDefault() try { await fetch(`URL/banners/${params.id}.json`,{ method: "PUT", body: JSON.stringify({ description: descriptionRef.current.value, img: imgRef.current.value }), headers: { 'Content-Type': 'application/json' } }) history.push(`/banners/${params.id}`); } catch (err) { console.error('更新失败:', err) // 这里可以加错误提示逻辑 } }
内容的提问来源于stack exchange,提问作者Frozendawn
相关产品推荐
相关产品推荐

