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

React Router点击当前页面菜单时如何避免页面重渲染?

点击当前页面路由链接时避免重渲染的实现方案

问题背景

我没找到类似问题的解答,想确认以下需求是否可实现:为优化性能,点击菜单栏中当前所在页面的链接时,能否避免页面刷新/重渲染?

当前使用的路由配置如下:

<Routes>
        <Route path='/' element={<Login />} />

        <Route element={<WebsiteBars />}>
          <Route path='/dashboard' element={<Dashboard />} />
          <Route path='/table' element={<Table/>} />
          <Route path='/settings' element={<UserSettings />} />
          <Route path='/help' element={<HelpPage />} />
        </Route>
</Routes>

菜单栏、应用栏、页脚等均封装在WebsiteBars组件中,每个菜单项基于Link组件实现(如to="/settings")。目前遇到的问题是:当处于Table页面时,再次点击菜单中的Table链接,页面会触发重渲染,且每次进入页面时生成的假数据会新增更多行——这是我希望避免的行为。

完整的App.js结构:

<VesselProvider>
 <Routes>
        <Route path='/' element={<Login />} />

        <Route element={<WebsiteBars />}>
          <Route path='/dashboard' element={<Dashboard />} />
          <Route path='/table' element={<Table/>} />
          <Route path='/settings' element={<UserSettings />} />
          <Route path='/help' element={<HelpPage />} />
        </Route>
 </Routes>
</VesselProvider>

其中VesselProvider是自定义的上下文提供者。

涉及的Table组件代码:

DefaultTable组件

const DefaultTable = ({ data }) => {
  // 包含用于填充表格数据的useEffect等逻辑
  const { setRowData } = useVessel(); // 从VesselProvider获取上下文
  return <Table> ... </Table>; // 普通MUI Table组件,使用传入的data
}

假数据生成逻辑

const rows = [];

const randSize = faker.datatype.number({ min: 10, max: 150 });


function fakeData() {
    for (let i = 0; i < randSize; i++) {

        rows.push(
            {
                status: faker.helpers.arrayElement(['sent', 'waiting', 'missing', 'resolved', 'read', 'created', 'modified']),
                ID: faker.random.numeric(6),
                filename: `${randTitle}.${faker.helpers.arrayElement(['xml', 'pptx'])}`,
                filesize: faker.datatype.number({ min: 10, max: 200 }) + "KB",
                subject: faker.helpers.arrayElement(['Invoice', 'Order']),
            }
        );
    }
    return rows;
}

const Table=()=>{
 return <DefaultTable data={fakeData()} />
}

核心疑问

  • 能否让当前所在路径不触发重渲染?有没有办法告知路由不再执行路由操作,或在处于链接指向的同一路径时“禁用”该链接?
  • 如果改用真实后端API获取数据,能否避免这种“异常行为”?

解决方案

1. 禁用当前路径的菜单链接

通过useLocation钩子获取当前路由路径,对比菜单项的to属性,当路径匹配时,给Link添加禁用样式并阻止点击交互:

import { Link, useLocation } from 'react-router-dom';

const MenuItem = ({ to, label }) => {
  const location = useLocation();
  const isActive = location.pathname === to;

  return (
    <Link
      to={to}
      style={{ 
        pointerEvents: isActive ? 'none' : 'auto', 
        opacity: isActive ? 0.6 : 1 
      }}
    >
      {label}
    </Link>
  );
};

2. 阻止同路径的路由跳转

若不想修改样式,可自定义Link组件,在点击时判断当前路径与目标路径是否一致,一致则阻止默认跳转行为:

import { Link, useLocation, useNavigate } from 'react-router-dom';

const CustomLink = ({ to, children }) => {
  const location = useLocation();
  const navigate = useNavigate();

  const handleClick = (e) => {
    if (location.pathname === to) {
      e.preventDefault(); // 阻止默认路由跳转
    }
  };

  return (
    <Link to={to} onClick={handleClick}>
      {children}
    </Link>
  );
};

3. 修复Table组件的数据生成逻辑

你遇到的“新增更多行”问题,本质是全局变量rows被重复添加数据,而非路由重渲染直接导致。即使不触发路由跳转,只要组件重新渲染,fakeData()就会往全局rows数组里新增数据。

修改假数据生成逻辑,将rows移到函数内部,并使用useMemo缓存数据:

function fakeData() {
    const rows = []; // 每次调用都创建新数组,避免全局污染
    const randSize = faker.datatype.number({ min: 10, max: 150 });
    for (let i = 0; i < randSize; i++) {
        rows.push(
            {
                status: faker.helpers.arrayElement(['sent', 'waiting', 'missing', 'resolved', 'read', 'created', 'modified']),
                ID: faker.random.numeric(6),
                filename: `${randTitle}.${faker.helpers.arrayElement(['xml', 'pptx'])}`,
                filesize: faker.datatype.number({ min: 10, max: 200 }) + "KB",
                subject: faker.helpers.arrayElement(['Invoice', 'Order']),
            }
        );
    }
    return rows;
}

const Table=()=>{
  // 空依赖数组,仅在组件挂载时生成一次数据
  const tableData = useMemo(() => fakeData(), []); 
  return <DefaultTable data={tableData} />
}

关于真实API的说明

改用真实后端API后,若你的数据获取逻辑是在组件挂载时调用一次(例如使用useEffect且依赖为空数组),那么即使路由触发重渲染,只要组件未被卸载再挂载,就不会重复请求数据。

结合前面的路由优化方案,阻止同路径的路由跳转后,组件不会因点击当前链接而重新渲染,自然也不会重复发起API请求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 17:20:33