reactjs React useEffect与Intersection Observer

qgzx9mmu  于 4个月前  发布在  React
关注(0)|答案(1)|浏览(60)

我正在努力寻找一种模式,适用于我正在使用的无限滚动组件作为参考。我正在使用react-intersection-observer钩子。问题是,当inView状态为true时,我的fetchData函数被调用了两次。我已经尝试了很多解决方案,但似乎都不起作用。流程似乎是:
1.页面加载inView为false。
1.用户滚动inView变为真。
1.异步调用fetchData,useEffect结束。

  1. res最终返回,setQueryData最终更新状态。
    1.这会触发useEffect再次执行,但由于数据刚刚被设置,它还没有被呈现,并将inView链接组件推到一边。
    1.由于inView仍然是true,因此执行另一个fetchData
    看起来我需要在useEffect运行后立即使inView为false,但不确定这是否可能或正确,任何建议都将非常感谢!
type LoadMoreState = {
  data: QueryDatabaseResponse[];
  nextCursor: string | undefined;
};

export function LoadMore({ cursor }: { cursor: string }) {
  const { ref, inView } = useInView();
  const [queryData, setQueryData] = useState<LoadMoreState>({
    data: [],
    nextCursor: cursor,
  });

  useEffect(() => {
    const fetchData = async () => {
      if (inView) {
        try {
          const res = await getGoodFirstIssues({
            page_size: 10,
            start_cursor: queryData.nextCursor,
          });
          setQueryData((prevData) => ({
            data: prevData.data.concat(res),
            nextCursor: res.next_cursor || undefined,
          }));
        } catch (error) {
          console.log("There was an error fetching the data", error);
        }
      }
    };
    fetchData();
  }, [inView, queryData]);

字符串

aiazj4mn

aiazj4mn1#

问题是,由于nextCursor,您需要在useEffect中包含queryData,但它也会触发useEffect,而inView仍然是true
next_cursor存储在ref(nextCursorRef)中,并将其从useEffect的依赖项中删除:

export function LoadMore({ cursor }: { cursor: string }) {
  const nextCursorRef = useRef<string | undefined>();
  const { ref, inView } = useInView();
  const [queryData, setQueryData] = useState<QueryDatabaseResponse[]>([]);

  useEffect(() => {
    const fetchData = async () => {
      if (inView) {
        try {
          const res = await getGoodFirstIssues({
            page_size: 10,
            start_cursor: nextCursorRef.current,
          });
          
          nextCursorRef.current = res.next_cursor || undefined;
          setQueryData((prevData) => prevData.concat(res));
        } catch (error) {
          console.log("There was an error fetching the data", error);
        }
      }
    };
    fetchData();
  }, [inView]);

字符串
我还将进一步重构它,以防止在inViewfalse时定义和调用fetchData

export function LoadMore({ cursor }: { cursor: string }) {
  const nextCursorRef = useRef<string | undefined>();
  const { ref, inView } = useInView();
  const [queryData, setQueryData] = useState<QueryDatabaseResponse[]>([]);

  useEffect(() => {
    if (!inView) return undefined; // if not in view no need to define and call fetchData

    const fetchData = async () => {
      try {
        const res = await getGoodFirstIssues({
          page_size: 10,
          start_cursor: nextCursorRef.current,
        });

        nextCursorRef.current = res.next_cursor || undefined;
        setQueryData((prevData) => prevData.concat(res));
      } catch (error) {
        console.log("There was an error fetching the data", error);
      }
    };
    fetchData();
  }, [inView]);

相关问题