import { fireEvent, waitFor } from '@testing-library/react' import * as React from 'react' import { ErrorBoundary } from 'react-error-boundary' import { createQueryClient, queryKey, renderWithClient, setActTimeout, sleep, } from './utils' import type { QueryClient } from '..' import { QueryCache, useIsFetching, useQuery } from '..' describe('useIsFetching', () => { // See https://github.com/tannerlinsley/react-query/issues/105 it('should update as queries start and stop fetching', async () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) const key = queryKey() function IsFetching() { const isFetching = useIsFetching() return
isFetching: {isFetching}
} function Query() { const [ready, setReady] = React.useState(false) useQuery( key, async () => { await sleep(50) return 'test' }, { enabled: ready, }, ) return } function Page() { return (
) } const { findByText, getByRole } = renderWithClient(queryClient, ) await findByText('isFetching: 0') fireEvent.click(getByRole('button', { name: /setReady/i })) await findByText('isFetching: 1') await findByText('isFetching: 0') }) it('should not update state while rendering', async () => { const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) const key1 = queryKey() const key2 = queryKey() const isFetchings: number[] = [] function IsFetching() { const isFetching = useIsFetching() isFetchings.push(isFetching) return null } function FirstQuery() { useQuery(key1, async () => { await sleep(100) return 'data' }) return null } function SecondQuery() { useQuery(key2, async () => { await sleep(100) return 'data' }) return null } function Page() { const [renderSecond, setRenderSecond] = React.useState(false) React.useEffect(() => { setActTimeout(() => { setRenderSecond(true) }, 50) }, []) return ( <> {renderSecond && } ) } renderWithClient(queryClient, ) await waitFor(() => expect(isFetchings).toEqual([0, 1, 1, 2, 1, 0])) }) it('should be able to filter', async () => { const queryClient = createQueryClient() const key1 = queryKey() const key2 = queryKey() const isFetchings: number[] = [] function One() { useQuery(key1, async () => { await sleep(10) return 'test' }) return null } function Two() { useQuery(key2, async () => { await sleep(20) return 'test' }) return null } function Page() { const [started, setStarted] = React.useState(false) const isFetching = useIsFetching(key1) isFetchings.push(isFetching) return (
isFetching: {isFetching}
{started ? ( <> ) : null}
) } const { findByText, getByRole } = renderWithClient(queryClient, ) await findByText('isFetching: 0') fireEvent.click(getByRole('button', { name: /setStarted/i })) await findByText('isFetching: 1') await findByText('isFetching: 0') // at no point should we have isFetching: 2 expect(isFetchings).toEqual(expect.not.arrayContaining([2])) }) describe('with custom context', () => { it('should update as queries start and stop fetching', async () => { const context = React.createContext(undefined) const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) const key = queryKey() function Page() { const [ready, setReady] = React.useState(false) const isFetching = useIsFetching(undefined, { context: context }) useQuery( key, async () => { await sleep(50) return 'test' }, { enabled: ready, context, }, ) return (
isFetching: {isFetching}
) } const { findByText, getByRole } = renderWithClient( queryClient, , { context, }, ) await findByText('isFetching: 0') fireEvent.click(getByRole('button', { name: /setReady/i })) await findByText('isFetching: 1') await findByText('isFetching: 0') }) it('should throw if the context is not passed to useIsFetching', async () => { const context = React.createContext(undefined) const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) const key = queryKey() function Page() { const isFetching = useIsFetching() useQuery(key, async () => 'test', { enabled: true, context, useErrorBoundary: true, }) return (
isFetching: {isFetching}
) } const rendered = renderWithClient( queryClient,
error boundary
}>
, { context, }, ) await waitFor(() => rendered.getByText('error boundary')) }) }) it('should show the correct fetching state when mounted after a query', async () => { const queryClient = createQueryClient() const key = queryKey() function Page() { useQuery(key, async () => { await sleep(10) return 'test' }) const isFetching = useIsFetching() return (
isFetching: {isFetching}
) } const rendered = renderWithClient(queryClient, ) await rendered.findByText('isFetching: 1') await rendered.findByText('isFetching: 0') }) })