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

React路由跳转后组件不刷新 useEffect未触发问题

问题根因

CrudDemo组件中拉取列表数据的useEffect依赖数组为空,仅会在组件首次挂载时执行一次。React Router导航到当前已挂载的同路径组件时,默认会复用已有组件实例,不会触发组件卸载重挂载,因此删除完成后跳转回/CrudDemo路径时,组件不会重新执行useEffect拉取最新数据,页面就会一直展示删除前的旧数据。

解决方案

方案1:抽离数据拉取逻辑,删除成功后主动触发重拉(推荐,体验最优)

不需要做无意义的同路径跳转,删除成功后直接触发列表数据刷新,没有多余路由动作,页面响应更快。

  1. 修改CrudDemo组件,抽离独立的数据拉取函数,逐层传递给操作按钮组件:
function CrudDemo(props) {
  const navigate=useNavigate();
  // 所有useState统一放到组件顶部,符合Hooks调用规范
  const [PersonList, setPersonList] = useState();

  // 抽离可重复调用的列表拉取逻辑
  const fetchPersonList = () => {
    axios.get('http://localhost:60359/api/person/getpersons').then((res)=>{
      setPersonList(res.data);
    })
  }

  // 首次挂载时拉取数据
  useEffect(()=>{
    fetchPersonList();
  },[])

  return (
    <div className="app">
      <h2>All students <span role="img" aria-labelledby="love">📫</span></h2>
      <button type="button" className="btn btn-info"onClick={() => navigate('/SavePerson/')}>Add Person</button> 
      <table className="table" >
              <TableHeader></TableHeader>
              <tbody>
              {PersonList&&PersonList.map((student,i) => {
         return (
          <TableRow key={student.id} obj={student} onRefresh={fetchPersonList}></TableRow>
         );
      })}
</tbody>
            </table>
    </div>
  );
}
export default CrudDemo;
  1. 修改TableRow组件,透传刷新回调函数:
function TableRow(props) {
  return (
    <tr >
    <th>{props.obj.id}</th>
    <th>{props.obj.personName}</th>
    <th>
    {
        (props.obj.city!=null&&props.obj.city.name.length >0)
          ? <div> {props.obj.city.name}  </div> 
          : <div> </div> 
      }
</th>
    <th>{props.obj.personPhoneNumber}</th>
    <th>
      <TableAction id={props.obj.id} onRefresh={props.onRefresh}></TableAction>
    </th>
        </tr>
  );
}
export default TableRow
  1. 修改TableAction组件,删除成功后直接调用刷新函数,移除多余的同路径跳转:
function TableAction(props) {
const navigate=useNavigate();

const handleClick = (e) => {
  axios.get('http://localhost:60359/api/person/DeletePerson/'+props.id).then((res)=>{
    console.log('person deleted message :',res.data);
    // 删除成功直接拉取最新列表数据
    props.onRefresh();
   })
};

  return (
    <div>
<button type="button" className="btn btn-info"onClick={() => navigate('/PersonDetail/'+props.id,{state:{id:props.id}})}>Details</button> 
<button type="button" className="btn btn-danger"onClick={handleClick}>Delete</button> 
    </div>
);
}
export default TableAction

方案2:保留同路径跳转逻辑,通过依赖变化触发useEffect执行

如果业务要求必须保留跳转同路由的逻辑,可以通过两种方式实现刷新:

  1. 给路由配置增加动态key,强制导航时重挂载组件:
// 路由配置处修改,每次导航location.key都会生成新值,触发组件重挂载
<Route path="/CrudDemo" element={<CrudDemo />} key={location.key} />
  1. 修改useEffect依赖项,监听路由变化触发数据拉取:
// CrudDemo组件内修改useEffect
useEffect(()=>{
  axios.get('http://localhost:60359/api/person/getpersons').then((res)=>{
    setPersonList(res.data);
  })
// 依赖location.key,每次导航到当前页key变化就会重新执行
},[location.key])

使用该方案时,跳转代码建议加replace参数,避免历史栈堆积重复记录:

navigate('/CrudDemo/', {replace: true})
优化建议
  • 原代码中声明的ShouldRefresh状态没有实际使用,可以直接删除减少冗余代码。
  • 删除操作建议使用DELETE请求方法,不要用GET方法触发数据修改,不符合接口规范,也容易被浏览器缓存、爬虫误触发。

内容的提问来源于stack exchange,提问作者Amir Kian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:51:25