react钩子的常见场景:如何在不导致无限渲染的情况下更改钩子依赖关系



我正在编写一个React应用程序,我有一个常见的场景,我想知道如何从设计的角度解决,而不是使用变通方法。

我经常处于这样一种情况,即我必须更改钩子本身内部的钩子依赖关系。

在这种情况下,我有一个表,我正在编写一个处理分页的组件。分页所基于的三个主要变量是:行数、页面数和每页的项目数。挂钩在这里:

const [page, setPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(5);
useEffect(() => {
let fixedItemsPerPage = itemsPerPage;
let fixedPage = page;
if (itemsPerPage > filteredRequests.length) {
fixedItemsPerPage = filteredRequests.length;
fixedPage = 1;
}
const paginatedFilteredRequests = filteredRequests.slice(
fixedItemsPerPage * (fixedPage - 1),
fixedItemsPerPage * fixedPage,
);
setVisibleRequests(paginatedFilteredRequests);
}, [filteredRequests, itemsPerPage, page]);

因此,只要其中一个变量发生变化,我就会重新运行钩子,并根据分页变量调整visibleRequests的数组。我需要辅助变量fixedItemsPerPagefixedPage的原因是,如果我选择一个大于行数组长度的itemsPerPageslice函数将越界,或者如果我选择第2页,然后调整itemsPerPage以包括表中的所有项目,我仍将在第2页中,它将不显示任何内容,而显示所有结果。

显然,这是一种变通方法,理想情况下,我想用setItemsPerPagesetPage设置这些变量,但如果我这样做,我将导致无限渲染。

我该如何解决这个问题?

我们这里缺少一些信息-如果我将页面设置为2,然后将每页的项目数设置为高于总结果数,您希望发生什么
如果我转到第5页,并将每页的项目设置为3页的内容,该怎么办?

假设您想将页面重新设置为最后一个可用页面(因此在上面的示例中,5将变为3(,您可以执行以下操作:

const [page, setPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(5);

useEffect(() => {
// No effect to run if there's no data
if (filteredRequests.length === 0) return;
// If the current page is too far forward
if (itemsPerPage * (page - 1) >= filteredRequests.length) {
const lastPage = Math.ceil(filteredRequests.length / itemsPerPage);
setPage(lastPage);
}
}, [itemsPerPage, page, filteredRequests])
const visibleRequests = useMemo(() => {
return filteredRequests.slice(
itemsPerPage * (page - 1),
itemsPerPage * page
);
}, [filteredRequests, itemsPerPage, page]);

我把你使用的代码分成两个钩子:

  • useEffect-对lastPage执行状态验证
  • useMemo-计算可见请求

如果你太过火,useEffect钩子将被调用两次,因为它正在调用setPage,而page是它的一个依赖项。但考虑到里面的逻辑,这没关系-你永远不会引起无限循环,因为在useEffect中调用setPage后,后续渲染将不会有问题的数据

此外,用slice遍历索引是可以的,它只会返回一个空数组(这是有道理的,因为如果第1页中有所有结果,那么第2页就是空的(

您可以使用useRef而不是useState,以确保只更新引用。

您可以做的另一件事是将以前的状态与新更改的状态进行比较。如果更改没有意义,可以提前返回,从而防止无限次重新渲染。

请查看官方React.js常见问题解答:https://reactjs.org/docs/hooks-faq.html#how-获取之前的道具或状态

相关内容

最新更新