diff --git a/src/index/use-swr.ts b/src/index/use-swr.ts index 4c1a96d0f..de8363a92 100644 --- a/src/index/use-swr.ts +++ b/src/index/use-swr.ts @@ -543,7 +543,7 @@ export const useSWRHandler = ( // Trigger the successful callback if it's the original request. if (shouldStartNewRequest) { if (callbackSafeguard()) { - getConfig().onSuccess(newData, key, config) + getConfig().onSuccess?.(newData, key, config) } } } catch (err: any) { diff --git a/test/use-swr-config-callbacks.test.tsx b/test/use-swr-config-callbacks.test.tsx index db6438e8d..2c409666f 100644 --- a/test/use-swr-config-callbacks.test.tsx +++ b/test/use-swr-config-callbacks.test.tsx @@ -200,6 +200,32 @@ describe('useSWR - config callbacks', () => { expect(discardedEvents).toEqual([key]) }) + it('should not cause infinite loading when onSuccess is undefined', async () => { + const key = createKey() + let fetchCount = 0 + function Page() { + const { data, isLoading } = useSWR( + key, + () => { + fetchCount++ + return createResponse('ok') + }, + { + onSuccess: undefined + } + ) + return
{isLoading ? 'loading' : `data: ${data}`}
+ } + + renderWithConfig() + screen.getByText('loading') + + await screen.findByText('data: ok') + // Wait a bit to ensure no extra retries are triggered. + await act(() => sleep(100)) + expect(fetchCount).toBe(1) + }) + it('should not trigger the onSuccess callback when discarded', async () => { const key = createKey() const discardedEvents = []