代码之家  ›  专栏  ›  技术社区  ›  Sheppard25

无限滚动更新数据两次

  •  0
  • Sheppard25  · 技术社区  · 5 年前

    我有一个延迟加载的表(无限滚动)。不幸的是,我不知道为什么,但它更新了 data 当我滚动到底部时,会出现两次。因此,对graphql进行了两个查询,而不是一个查询。如果我删除 数据 从…起 fetchMore 依赖关系它工作得很好(但是,eslint会抛出警告,所以它不是一个解决方案)。此外,当我删除滚动条并用手动按钮替换它,然后单击以获取时,效果也很好,所以我不知道问题是在查询中还是在 WithInfiniteScroll

    const LIMIT = 10;
    
    const updateQuery = (
      previousQueryResult: GetStaffQuery,
      options: {
        fetchMoreResult?: GetStaffQuery;
        variables?: GetStaffQueryVariables;
      }
    ): GetStaffQuery => {
      const {fetchMoreResult} = options;
      const currentNodes = previousQueryResult.staff.nodes || [];
      const newNodes = fetchMoreResult?.staff.nodes || [];
      const newResult = {
        staff: {
          ...fetchMoreResult?.staff,
          nodes: [...currentNodes, ...newNodes],
        },
      };
    
      return newResult;
    };
    
    export const useUsersList = () => {
      const [isInitialFetching, setIsInitialFetching] = useState(true);
    
      const {data, fetchMore: handleFetchMore, loading} = useGetStaffQuery({
        variables: {limit: LIMIT, nextToken: null},
        onCompleted: () => {
          setIsInitialFetching(false);
        },
      });
    
      useEffect(() => {
        debugger; //triggered twice when scrolled to the bottom
      }, [data]);
    
      const fetchMore = useCallback(() => {
        const nextToken = data?.staff.nextToken || null;
    
        if (nextToken && !loading && !isInitialFetching) {
          const queryVariables: GetStaffQueryVariables = {
            limit: LIMIT,
            nextToken,
          };
          handleFetchMore({variables: queryVariables, updateQuery});
        }
      }, [data, handleFetchMore, isInitialFetching, loading]);
    
      return {
        isLoading: loading,
        canLoadMore: Boolean(data?.staff.nextToken && !loading) || false,
        fetchMore,
        users: data?.staff.nodes || [],
      };
    };
    

    无限滚动:

    import React, {useEffect, ReactNode} from 'react';
    import {useInView} from 'react-intersection-observer';
    
    type PropTypes = {
      children?: ReactNode;
      canLoadMore: boolean;
      onLoadMore: () => unknown;
    };
    
    const rootMargin = '400px';
    
    export const WithInfiniteScroll = ({
      children,
      canLoadMore,
      onLoadMore,
    }: PropTypes) => {
      const [ref, isElementInViewport] = useInView({
        rootMargin,
        skip: !canLoadMore,
      });
    
      useEffect(() => {
        if (canLoadMore && isElementInViewport) {
          onLoadMore();
        }
      }, [canLoadMore, isElementInViewport, onLoadMore]);
    
      return (
        <>
          {children}
          <div ref={ref} />
        </>
      );
    };
    

    和一些组件草稿:

      <WithInfiniteScroll canLoadMore={canLoadMore} onLoadMore={onLoadMore}>
        <div>
           {users.map(user => <span>{user.id}</span>)}
        </div>
    </WithInfiniteScroll>
    
    0 回复  |  直到 5 年前