最近这个项目为了使用户交互更加友好,每个页面路由都采用了lazyload的方式进行加载,分离js以使按需进行加载,其中,我将 Suspense 封装进入了一个函数,通过函数返回对应内容:
export const LazyImport: React.FC<{ lazy: LazyExoticComponent<ComponentType> }> = ({ lazy: Component }) => {
return (
<Suspense fallback={<PageLoader />}>
<Component />
</Suspense>
);
};
export const appRouters: RouteObject[] = [
{
path: 'dashboard',
element: <LazyImport lazy={lazy(() => import('@/pages/Dashboard'))} />,
},
{
path: 'order',
element: <LazyImport lazy={lazy(() => import('@/pages/Order/order'))} />,
}
]
之前的效果是这样:在第一次进入仪表盘页面,关于仪表盘页面的PageLoader组件会在合适的区域显示出来,但是,切换到其他页面的时候,PageLoader组件将不会在加载过程中展示。
原本的思路很简单,将重复的代码进行统一的的实现,其他地方就可以使用了,错就错在没有过多的考虑React渲染模式,对于React来说,组件的相同会导致其更新时尝试复用组件(节省开销),就像是我们循环遍历出来新的动态组件一样,我们要保持循环出来的每个组件都是全新的话,就需要给每一个组件添加一个不同的 key,这样的话,React在进行渲染的时候,每个LazyImport组件都是全新的,而不是复用旧的。
给每次调用LazyImport都加个不同的Key:
let _suspenseKey = 0;
export const LazyImport: React.FC<{ lazy: LazyExoticComponent<ComponentType> }> = ({ lazy: Component }) => {
_suspenseKey++;
return (
<Suspense key={_suspenseKey} fallback={<PageLoader />}>
<Component />
</Suspense>
);
};
完美解决

这个问题说简单也简单,就是脑袋里默认会觉得这么小的事情应该不会影响到这个,所以在遇到这种问题的时候往往第一时间想不到是这个,细心很重要。
作者近期使用React和Nest做了个开源的ERP/CRM系统在Github(https://github.com/luutuu/luutuu-erp)
欢迎各位通过以下方式一起交流
- github 的 issue
- 邮箱联系 lutultd@163.com