为什么React会用他们的linter插件强迫我添加我不想要的依赖项?
例如,我希望我的效果仅在certan值更改时才触发,但是linter告诉我在依赖项中添加偶数函数,而我不希望那样。
为什么强迫我这样做?我从中得到什么?
/**
* Gets all items, pages, until 250th.
*/
useEffect(() => {
let mounted = true;
if (loadUntil250th && !paginationProps.complete) {
mounted && setLoading(true);
let limit = 250 - paginationProps.page * BATCH_LIMIT;
fetchListItems(paginationProps, limit, paginationProps.page * BATCH_LIMIT)
.then((results) => {
if (mounted) {
setPaginationProps({
...paginationProps,
page: 250 / BATCH_LIMIT,
autoLoad: false,
complete: paginationProps.totalItems <= 250,
});
setListItems(results.listItems);
setLoading(false);
}
})
.catch((err) => {
logger.log('LOADMORE FAILED:', err);
mounted && setPaginationProps({ ...paginationProps, complete: true });
mounted && setLoading(false);
});
}
return () => {
mounted = false;
};
}, [loadUntil250th]);
它想要这种依赖关系数组,从而导致无限循环
[loadUntil250th, logger, paginationProps, setListItems]);
如果我不想要它们,我想了解为什么要这么做。
答案 0 :(得分:2)
“穷举-下降”棉绒规则旨在防范stale closures,其中useEffect
引用回调中使用的道具或状态,但不存在于依赖项数组中。由于logger
,paginationProps
和setListItems
在理论上可以在渲染之间进行更改,因此在useEffect
内引用它们而不将它们也包括在依赖项数组中以确保您可以始终接收最新数据并对其进行操作。您可以认为useEffect本质上是在创建状态和道具时生成所有状态和道具的快照,并在其依赖项之一发生更改时仅 对其进行更新。
例如,如果在依赖项列表中不包括paginationProps
,则如果fetchListItems
曾经修改过paginationProps
的值,那么useEffect
将无法访问该更新后的值loadUntil250th
更改。
如this answer中所述,部分问题是您对useEffect()的使用是 unidiomatic 。如果您要做的只是订阅对loadUntil250th
的更改,最好将此功能移到其他位置,并使用修改loadUntil250th
的代码来调用它。
如果要将代码保留在useEffect
钩中,则可以选择以下几种方式:
paginationProps
和setPaginationProps
源自useState
钩子,则可以通过passing a function到paginationProps
消除对setPaginationProps
的依赖性而不是对象。因此您的代码将变为:setPaginationProps(paginationProps => {
...paginationProps,
page: 250 / BATCH_LIMIT,
autoLoad: false,
complete: paginationProps.totalItems <= 250,
});
setListItems
inside the useEffect
hook。这样可以确保您可以控制该功能所依赖的任何道具/状态。如果那不可能,那么您可以选择几种方法。您可以将函数完全移出组件,以确保它不依赖道具或状态。另外,您可以将useCallback
hook与函数一起使用以控制其依赖性,然后将setListItems
列为另一个依赖性。logger
函数不太可能在渲染之间进行更改,因此您可以安全地将其保留在依赖项数组中(尽管linter期望这样做很奇怪)。如果您仍然好奇,this article有助于详细说明useEffect
和依赖项数组的实际工作方式。