re-render 多次调用的 useQuery 钩子只执行一次

问题描述 投票:0回答:1

我正在使用 useQuery 钩子来获取数据,它在重新渲染期间被多次调用,但是 onSuccess 回调只被调用一次。

export async function postWithoutCancellation({ queryKey, pageParam, responseType }) {
  const url = queryKey[0];
  let body = queryKey[1];
  if (pageParam) {
    body = { ...body, ...pageParam };
  }

  const { data } = await axiosInstance.post(url, body, {
    ...config1,
    responseType,
  });
  return data;
}

const [lazyLoadRowDataQuery, setlazyLoadRowDataQuery] = useState(null);
  const metricDataLazyLoad = useQuery(
    [
      `/api/call`,
      {
        ...filters,
        queries: getQueryMetrics(selectedDimensions, lazyLoadRowDataQuery),
        // ...(view_metrics ? { attributionType: view_metrics } : {}),
      },
    ],
    postWithoutCancellation,
    {
      enabled: !!lazyLoadRowDataQuery,
      onSuccess: (data) => {
        console.log('On success callback', data, lazyLoadRowDataQuery)
      }
    }
  );

useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        console.log('Entries', entries, timeouts.current)

        entries.forEach(e => {
          const rowKey = e?.target?.getAttribute('data-row-key') as string;
          if (e.isIntersecting) {
            const timerId = setTimeout(() => {
              // observer.unobserve(e.target)

              // handling
              const element = paginatedData.find(item => item.key === +rowKey);
              setlazyLoadRowDataQuery(element);
              // metricDataLazyLoad.refetch();
              // metricDataLazyLoad.mutation();

            }, 1000)  // delay for 1 second
            timeouts.current[rowKey] = timerId
          } else {
              clearTimeout(timeouts.current[rowKey])
          }
        })
      }, {
        root: tableRef.current.querySelector('.ant-table-body'),
        threshold: 0
      }
    );
    
    const tableRows = tableRef.current.querySelectorAll('.ant-table-row');
    // observer.observe(tableRows[0]);
    console.log('Table rows', tableRows, tableRef.current.querySelector('.ant-table-tbody'));
    if (Array.from(tableRows).length > 0) {
      Array.from(tableRows).forEach((item: any) => observer.observe(item))
    }

    return () => {
      if (Array.from(tableRows).length > 0) {
        Array.from(tableRows).forEach((item: any) => observer.disconnect(item))
      }
    };
  }, [paginatedData, timeouts]);

假设,如果视图中有5个元素,则回调将被调用5次,这将触发setlazyLoadRowDataQuery 5次,因此进行了5次网络调用,但仅调用一次onSuccess回调,这是针对最后一个数据。对于最初的 4 次调用,回调永远不会执行。

我尝试使用 useQueries 钩子,但状态维护有点复杂

reactjs next react-query
1个回答
0
投票

您在 useEffect 钩子中多次设置 lazyLoadRowDataQuery 状态,从而触发 useQuery 钩子多次获取数据。因此,onSuccess 回调只会为最后一次获取的数据调用。而不是 settimeout 你使用去抖动技术来延迟 setlazyLoadRowDataQuery 方法的执行,直到经过一定的时间,然后这将防止进行多次网络调用并确保onSuccess 回调只被调用一次

© www.soinside.com 2019 - 2024. All rights reserved.