在这篇文章中,我们将优化我们的列表组件,它显示数据。一旦我们通过它,你将学会如何提高你的应用程序的性能,使你的应用程序的体验更好。不多说了,让我们开始吧!
为什么要偷懒加载你的数据?
想象一下,你的应用程序有一个屏幕,有三个列表组件正在渲染,每个列表都有成千上万的记录,正在用REST从你的服务器获取。现在你可以一次性获得所有的数据,但这意味着你与服务器的通信可能需要时间,因为它必须带来大量的数据,这浪费了用户的时间和你的应用程序的性能。如何解决这个问题呢?
- 给你的用户分页,这样他们就可以访问他们自己选择的页面。
- 一旦用户到达列表的末尾,就触发下一批的数据
现在,这两种解决方案都是有效的,因为它们服务于不同的目的,并根据需求来使用,但在这个解决方案中,我们要做的是一旦用户到达列表的末尾就自动获取下一批数据。
无限滚动React
我们将使用一个包来支持无限滚动的列表,如果你喜欢,可以自己制作一个:
npm i react-infinite-scroll-component
我们遵循我们的一个关于react query的教程的代码基础。按照该教程中的分层架构,我们将在我们的API层中做一些改变
const fetchPlanets = async ({ pageParam = 1 }) => { return axiosInstance({ url: `planets/?page=${pageParam}`, method: "GET", }).then(({ data }) => { const response = { results: data?.results, next: data.next === null ? undefined : pageParam + 1, }; return response; });};
我们添加了默认值为1的pageParams,我们的服务器原始响应看起来是这样的
{
"count": 60,
"next": "https://swapi.dev/api/planets/?page=2",
"previous": null,
"results": [
{
"name": "Tatooine",
"rotation_period": "23",
"orbital_period": "304",
"diameter": "10465",
"climate": "arid",
"gravity": "1 standard",
"terrain": "desert",
"surface_water": "1",
"population": "200000",
...
},
]
}
在我们的自定义钩子上,我们将用react query的useQuery替换useInfiniteQuery,这将帮助我们实现懒惰加载,并再次以最小的代码实现。
const usePlanets = () => {
return useInfiniteQuery(["get-planets"], fetchPlanets, {
getNextPageParam: (lastPage) => lastPage.next,
select: (data) => data,
});
};
我们在这里使用了getNextPageParam选项,这样我们就可以使用react query来检查下一页的内容,现在我们已经完成了自定义钩子,让我们进入实际的组件
const CustomComponent = () => {
const { data: planets, isLoading, hasNextPage } =
usePlanets();
const [dataLength, setDataLength] = useState(0);
useEffect(() => {
if (!!planets && !!planets?.pages && planets?.results) {
setDataLength(
planets.pages.reduce((counter, page) => {
return counter + page.results.length;
}, 0)
);
}
}, [planets]);
return (
<InfiniteScroll
dataLength={dataLength}
next={fetchNextPage}
hasMore={!!hasNextPage}
loader={<div>Automatically fetching next page...</div>}
>
{planets?.pages?.map((pageResult, i) => {
return (
<React.Fragment key={i}>
{pageResult.results.map((planet) => (
<Planet
key={planet.id}
planet={planet}
/>
))}
</React.Fragment>
);
})}
</InfiniteScroll>
)
}
export default CustomComponent
在这里,我们使用了之前安装的InfiniteScroll组件来延迟加载我们的列表,然后我们开始将我们的数据映射为组件的子节点,并从react query中提供next,hasMore和loader 。
关键时刻

总结
好吧,这篇很长,有很多代码
,但是我们做到了,给你自己一个饼干,你做得很好。我们学会了如何用react query的懒惰加载使我们的应用程序的体验变得无缝。当我们的行星列表在无限滚动的帮助下被懒惰地获取时。下一次见。在那之前,保重。