对于我的主页,我正在尝试使用带有交集观测器的可加载组件。当我的redux存储更新时,整个页面都会被重新绘制。我该如何避免这种情况?
import React from "react"
import loadable from "@loadable/component"
import { useSelector } from "react-redux"
const Index = () => {
const intersectState = useSelector(state => state.intersectState)
const BannerProducts = loadable(() =>
import("../components/bannerProducts/bannerProducts")
)
const SellingBulletPoints = loadable(() =>
import("../components/sellingBulletPoints/sellingBulletPoints")
)
const Category = intersectState.categoryComponent &&
loadable(() => import("../components/category/category"))
return (
<>
<BannerProducts />
<SellingBulletPoints />
{intersectState.categoryComponent && <Category />}
</>
)
}
export default Index
问题是React每次重新渲染组件时都错误地认为组件是新组件。
发生这种情况是因为每次渲染都会重新定义组件。
如果将这些延迟加载组件定义移动到渲染函数之外,那么它应该可以正常工作。
const BannerProducts = loadable(() =>
import("../components/bannerProducts/bannerProducts")
)
const SellingBulletPoints = loadable(() =>
import("../components/sellingBulletPoints/sellingBulletPoints")
)
const Category = loadable(() => import("../components/category/category"))
以下是它的工作原理:
loadable(()=>import('./component'))
调用只创建一个包装器组件,该组件在渲染时将挂起(或仅渲染null),直到完整的代码在浏览器中并准备好运行为止。在呈现该组件之前,代码分割代码不会在浏览器中加载。
因此,通过重新创建延迟加载包装器组件,您只需要添加额外的循环。事实上,您正在破坏React用来确定它是否是正在渲染的同一元素(即Component===Component
)的内容。因此,每次重新渲染父元素时,都会重新创建惰性加载包装器组件,从而导致其卸载/重新装载。
幸运的是,延迟加载得到了充分的优化,因此它只加载同一块一次——当延迟加载的组件首次渲染时(因此是import('./component')
行)。
为了理解这是如何工作的,以及为什么您的组件被重新装载,我设置了一个代码沙箱,其中有3个组件都有相同的代码(尽管名称和字符串不同)。
import { useEffect } from "react";
console.log("CodeSplit Code loaded!");
export default function CodeSplit() {
useEffect(() => {
console.log(`CodeSplit Mounted`);
return () => {
console.log(`CodeSplit Unmounted`);
};
}, []);
return <div>CodeSplit</div>;
}
如果运行codesandbox,则有三个组件:NormalCode
-作为基本bundle的一部分同步呈现的代码。加载主捆绑包时,NormalCode Code Loaded
消息会记录为代码运行。
CodeSplit
-代码使用loadable
延迟加载,但使用方式正确。单击show splits
按钮后,会立即记录CodeSplit Code Loaded
消息。发生这种情况是因为即使<CodeSplit />
在调用中,这也是第一次呈现CodeSplit
延迟加载组件。这样,当它被渲染并输入时,就不会再有CodeSplit Mounted
和CodeSplit Unmounted
消息了。
CodeSplitGoofed
-代码使用loadable
进行延迟加载,但延迟加载组件是在App
组件的渲染中生成的。这种行为与延迟加载方面的CodeSplit
相同,但当您在输入中键入时,您可以从CodeSplitGoofed Mounted
和CodeSplitGoofed Unmounted
控制台日志中看到,每当App
组件重新渲染时,该组件都会被卸载和重新装载。原因如上——React不知道这是以前的同一个组件。
https://codesandbox.io/s/so-stop-react-rerendering-page-with-dynamic-import-mch7g?file=/src/App.js