如何在useEffect中包含缺失的依赖,但防止函数的无限循环执行?



我正在研究一个相当简单的React功能组件,它从URL获得一个值(tag),并从firestore请求与该tag(inlc)对应的文档。Firestore查询游标(与加载更多按钮一起使用)。整个组件由函数声明和调用该函数的useEffect钩子组成。

基本上组件工作正常。但是有一个问题:ESLint告诉我,我需要将该函数包含为useEffect钩子的依赖项:

React Hook useEffect缺少一个依赖项:'getNextImages'。要么包含它,要么删除依赖数组react-hooks/精疲力竭-deps

如果我把这个函数包含到依赖数组中,或者完全删除依赖数组,那么这个组件当然会陷入一个无限的渲染循环。我可以用// eslint-disable-next-line跳过ESLint的依赖数组,但感觉不对。

我试图通过将getNextImages包装成useCallback钩子来修复此问题,但没有成功。但也许我用错了方法。我从来没有使用过useCallback之前…

有谁能给我个提示吗?

你可以在https://codesandbox.io/s/great-liskov-d12l3?file=/src/App.js找到我的组件。或:

import { useEffect, useState } from "react";
import firebase from "firebase";
import { useParams } from "react-router-dom";
const GalleryTag = () => {
//const [isPending, setIsPending] = useState(true);
//const [galleryData, setGalleryData] = useState([]);
//const [lastDocument, setLastDocument] = useState(null);
//const [isLastPage, setIsLastPage] = useState(false);
const numImagesPerPage = 20;
const { tag } = useParams();
const getNextImages = (lastDocument) => {
let query;
!lastDocument
? (query = firebase
.firestore()
.collectionGroup("images")
.where("showinapp", "==", true)
.where("tags", "array-contains", tag)
.orderBy("createdate", "desc")
.limit(numImagesPerPage)
.get())
: (query = firebase
.firestore()
.collectionGroup("images")
.where("showinapp", "==", true)
.where("tags", "array-contains", tag)
.orderBy("createdate", "desc")
.startAfter(lastDocument)
.limit(numImagesPerPage)
.get());
query
.then((data) => {
setIsLastPage(data.empty);
setIsPending(false);
setLastDocument(data.docs[data.docs.length - 1]);
setGalleryData((galleryData) => galleryData.concat(data.docs));
})
.catch((error) => console.error(error));
};
useEffect(() => {
getNextImages();
}, [tag]);
return <>JSX goes here then</>;
};
export default GalleryTag;

尝试将function移动到useEffect回调:


useEffect(() => {
const getNextImages = (lastDocument) => {
let query;
!lastDocument
? (query = firebase
.firestore()
.collectionGroup("images")
.where("showinapp", "==", true)
.where("tags", "array-contains", tag)
.orderBy("createdate", "desc")
.limit(numImagesPerPage)
.get())
: (query = firebase
.firestore()
.collectionGroup("images")
.where("showinapp", "==", true)
.where("tags", "array-contains", tag)
.orderBy("createdate", "desc")
.startAfter(lastDocument)
.limit(numImagesPerPage)
.get());
query
.then((data) => {
setIsLastPage(data.empty);
setIsPending(false);
setLastDocument(data.docs[data.docs.length - 1]);
setGalleryData((galleryData) => galleryData.concat(data.docs));
})
.catch((error) => console.error(error));
};
getNextImages();
}, [tag]);

现在我得到了解决方案。它叫做useCallback钩子

在玩了useCallback和它的依赖数组之后,我只需要在这个钩子中包装函数getNextImages()并设置它的依赖项(在这种情况下是tag)。

然后我可以将函数getNextImages设置为以下useEffect钩子的依赖项…并且voil: ESLint现在很高兴(当然也包括构建过程)。重新渲染和无限执行循环也被阻止。

下面是工作代码:

const getNextImages = useCallback(
(lastDocument) => {
let query;
!lastDocument
? (query = firebase
.firestore()
.collectionGroup("images")
.where("showinapp", "==", true)
.where("tags", "array-contains", tag)
.orderBy("createdate", "desc")
.limit(numImagesPerPage)
.get())
: (query = firebase
.firestore()
.collectionGroup("images")
.where("showinapp", "==", true)
.where("tags", "array-contains", tag)
.orderBy("createdate", "desc")
.startAfter(lastDocument)
.limit(numImagesPerPage)
.get());
query
.then((data) => {
setIsLastPage(data.empty);
setIsPending(false);
setLastDocument(data.docs[data.docs.length - 1]);
setGalleryData((galleryData) => galleryData.concat(data.docs));
})
.catch((error) => console.error(error));
},
[tag]
);
useEffect(() => {
getNextImages();
setPageTitle(`Bilder zum Tag »${tag}«`);
sendAnalytics("page_view", {
page_title: `Bilder zum Tag »${tag}«`,
});
}, [getNextImages, tag]);

相关内容

  • 没有找到相关文章

最新更新