react-router-cache-route icon indicating copy to clipboard operation
react-router-cache-route copied to clipboard

嵌套路由,缓存了的组件每次都会重新调用

Open ShowJoy opened this issue 3 years ago • 6 comments

求教,嵌套路由,缓存了的组件每次都会重新调用,导致页面很慢

index.js (入口文件)

import { getRoutes } from 'route.js'; // 下面的route.js文件
const routes = [
  {
    path: "/p",
    redirect: "/p/a/list",
    component: () => import("../layouts/Default"),
    children: [
      {
        path: "a",
        redirect: "/p/a/list",
        name: "AA",
        children: [
          {
            path: "list",
            name: "BB",
            component: () => import("../xx"),
          },
          {
            path: ":value/list",
            name: "CC",
            component: () => import("../xx"),
          },
        ],
      },
    ],
  },
];

render(
    <ConfigProvider locale={zhCN}>
      <Provider store={store}>
        <ConnectedRouter history={history}>{getRoutes(routes)}</ConnectedRouter>
        <ProgressPanel />
      </Provider>
    </ConfigProvider>,
    document.getElementById("app"),
  );

route.js

import React, { useEffect } from "react";
import Loadable from "react-loadable";
import { Redirect} from "react-router-dom";
import CacheRoute, { CacheSwitch } from "react-router-cache-route";

const getComponent = (route, subRoutes: any) => {
  let { component } = route;
  return Loadable({
    loader: async () => {
      const cpt = component();
      if (!cpt.then) {
        return cpt;
      }
      NProgress.start();
      return cpt.finally(() => NProgress.done());
    },
    loading: Loading,
    render(loaded: any, props: any) {
      const Component = loaded.default;
     console.log(''这里每次缓存过的组件都会重新渲染)
      return <Component {...props}>{subRoutes}</Component>;
    },
  });
};

export const getRoutes = (routes: RouteItem[] = [], parentPath = "", parent?: RouteItem) => {
  if (routes.length === 0) {
    return null;
  }
  return (
    <CacheSwitch>
      {routes.map((route, i) => {
        const { children, path, auth, exact } = route;
        const linkPath =
          path.indexOf("/") === 0 ? path : `${parentPath}/${path}`.replace(/\/+/g, "/");
        route.parent = parent;
        route.path = linkPath;
        const ComponentWithSubRoutes = getComponent(route, getRoutes(children, linkPath, route));
        return (
          <CacheRoute
            strict
            key={i}
            path={linkPath}
            cacheKey={linkPath}
            exact={exact}
            component={ComponentWithSubRoutes}
          />
        );
      })}
      {parent && parent.redirect ? (
        <Redirect strict={false} exact={parent.exact} from={parent.path} to={parent.redirect} />
      ) : null}
      {!parent ? <Redirect strict exact from="/" to="/p" /> : undefined}
    </CacheSwitch>
  );
};

感谢关注

注: react-router-dom v5

ShowJoy avatar Jul 13 '21 11:07 ShowJoy

目前每次 getComponent 都会重新生成一个组件定义,会被 React 认为是全新的组件,按首次渲染看待

不要在 map 里 getComponent,每个组件仅定义一次再试试

CJY0208 avatar Jul 14 '21 01:07 CJY0208

目前每次 getComponent 都会重新生成一个组件定义,会被 React 认为是全新的组件,按首次渲染看待

不要在 map 里 getComponent,每个组件仅定义一次再试试

map只会跑一次,每个组件只会定义一次吧,没有用cacheswitch的话就只会渲染当前的组件

ShowJoy avatar Jul 14 '21 02:07 ShowJoy

~~map 应该会跑多次,每次渲染都会跑,可以打个 log 看一下~~

看了一下你代码,感觉确实像是只跑一次,现在是缓存完全不生效吗?

最好还是加一个 log 确认一下渲染情况

CJY0208 avatar Jul 14 '21 03:07 CJY0208

缓存生效了,就是缓存过的页面还会渲染一次,缓存越多那就越卡了,eg,访问页面路径A->B->C, 那访问C页面时,A,B缓存过的页面还是会rerender渲染一次

ShowJoy avatar Jul 14 '21 07:07 ShowJoy

用 memo 包裹一下 getRoutes

liuye1296 avatar Jul 20 '21 06:07 liuye1296

问题解决了吗

riminggit avatar Aug 11 '21 02:08 riminggit