reactjsreact-queryjotai

UseQuery refetch everytime my component's state changes, even when I set enabled to false


I have this custom hook that used to fetch multiple requests

import dashboardApi from '@api/dashboardApi'
import { queryKeys } from '@constants/queryKeys'
import { TOP_PROJECT_SORT } from '@models/projectCost'
import { UseQueryOptions, UseQueryResult, useQuery } from '@tanstack/react-query'
import { NotifyService } from '@utils/notify'
import { AxiosError } from 'axios'

function useGetExportPDFData(
  queryOptions?: UseQueryOptions<any, any, any, any>,
): UseQueryResult<any, any> {
  // if top member mode is custom time range, then don't pass query and cal API of previous data
  const requests = [
    dashboardApi.getTopProjects({
      sortBy: TOP_PROJECT_SORT.AverageCost,
      order: 'desc',
      limit: '6',
    }),
  ]

  return useQuery(
    [queryKeys.account],
    async () => {
      return await Promise.all(requests)
    },
    {
      enabled: false,
      onError: (error: AxiosError) => {
        NotifyService.error(error)
      },
      ...queryOptions,
    },
  )
}

export default useGetExportPDFData

The problem is whenever the 2 jotai state changes (topMemberTimeRange and customDateRange), it also refetch again, although I did set enable to false, I only want to trigger this when refetch is called. How to do that?

import MainPageLayout from '@components/layout/MainPageLayout'
import PersonalRevenueHeader from '@features/personal-revenue/components/PersonalRevenueHeader'
import { TopMemberMode } from '@features/personal-revenue/constant'
import useGetExportPDFData from '@features/personal-revenue/hooks/useGetExportPDFData'
import { RevenuetMember, TableRevenueMember, TopMemberResponse } from '@models/personalRevenue'
import { calculatePercentageChange } from '@utils/common'
import { useAtom } from 'jotai'
import _ from 'lodash'
import { Outlet } from 'react-router-dom'
import pdf from './pdf'
import { customTimeRange, topMemberTimeRangeQuery } from './store'

function PersonalRevenue() {
  const [topMemberTimeRange] = useAtom(topMemberTimeRangeQuery)
  const [customDateRange] = useAtom(customTimeRange)
  const { refetch } = useGetExportPDFData({
    enabled: false,
    refetchOnWindowFocus: false,
    refetchOnMount: false,
  })
  return (
    <MainPageLayout
      title="PERSONAL REVENUE"
      header={<PersonalRevenueHeader exportData={exportPDF} />}
    >
      <Outlet />
    </MainPageLayout>
  )
}

Solution

  • const requests = [
      dashboardApi.getTopProjects({
        sortBy: TOP_PROJECT_SORT.AverageCost,
        order: 'desc',
        limit: '6',
      }),
    ]
    

    This code is in the body of the hook, which means it will execute on every render. So every time your component renders, you call getTopProjects(/*...*/). This happens no matter whether the query is enabled, since this code is unrelated to the query.

    If you only want this code to execute when fetching the query, then move it into the query function:

    return useQuery(
      [queryKeys.account],
      async () => {
        const requests = [
          dashboardApi.getTopProjects({
            sortBy: TOP_PROJECT_SORT.AverageCost,
            order: "desc",
            limit: "6",
          }),
        ];
        return await Promise.all(requests);
      },
      {
        enabled: false,
        onError: (error: AxiosError) => {
          NotifyService.error(error);
        },
        ...queryOptions,
      },
    );