diff --git a/_internal/utils/env.ts b/_internal/utils/env.ts index a292c3032..801ff1332 100644 --- a/_internal/utils/env.ts +++ b/_internal/utils/env.ts @@ -1,7 +1,6 @@ import React, { useEffect, useLayoutEffect } from 'react' import { hasRequestAnimationFrame, isWindowDefined } from './helper' - export const IS_REACT_LEGACY = !React.useId export const IS_SERVER = !isWindowDefined || 'Deno' in window diff --git a/infinite/index.ts b/infinite/index.ts index 990ed8252..1f8fd4a61 100644 --- a/infinite/index.ts +++ b/infinite/index.ts @@ -15,7 +15,8 @@ import { BareFetcher, useIsomorphicLayoutEffect, serialize, - withMiddleware + withMiddleware, + MutatorOptions } from 'swr/_internal' import type { @@ -197,13 +198,18 @@ export const infinite = ((useSWRNext: SWRHook) => | [undefined | Data[] | Promise | MutatorCallback] | [ undefined | Data[] | Promise | MutatorCallback, - boolean + undefined | boolean | MutatorOptions ] ) => { const data = args[0] + // When passing as a boolean, it's explicitly used to disable/enable + // revalidation. + const options = + typeof args[1] === 'boolean' ? { revalidate: args[1] } : args[1] || {} + // Default to true. - const shouldRevalidate = args[1] !== false + const shouldRevalidate = options.revalidate !== false // It is possible that the key is still falsy. if (!infiniteKey) return diff --git a/test/use-swr-config-callbacks.test.tsx b/test/use-swr-config-callbacks.test.tsx index 40bb56025..36d807989 100644 --- a/test/use-swr-config-callbacks.test.tsx +++ b/test/use-swr-config-callbacks.test.tsx @@ -57,7 +57,9 @@ describe('useSWR - config callbacks', () => { ) return (
mutate()}> - <>hello, {data}, {props.text} + <> + hello, {data}, {props.text} +
) } @@ -100,7 +102,9 @@ describe('useSWR - config callbacks', () => { if (error) return
{error.message}
return (
- <>hello, {data}, {props.text} + <> + hello, {data}, {props.text} +
) } diff --git a/test/use-swr-error.test.tsx b/test/use-swr-error.test.tsx index 8168fbacd..d9c90b33b 100644 --- a/test/use-swr-error.test.tsx +++ b/test/use-swr-error.test.tsx @@ -17,7 +17,11 @@ describe('useSWR - error', () => { createResponse(new Error('error!')) ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() @@ -37,7 +41,11 @@ describe('useSWR - error', () => { { onError: (_, errorKey) => (erroredSWR = errorKey) } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() @@ -63,7 +71,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() screen.getByText('hello,') @@ -93,7 +105,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() screen.getByText('hello,') @@ -130,7 +146,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() screen.getByText('hello,') @@ -158,7 +178,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() screen.getByText('hello,') @@ -186,7 +210,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() screen.getByText('hello,') @@ -241,7 +269,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() @@ -307,7 +339,11 @@ describe('useSWR - error', () => { }, dedupingInterval: 0 }) - return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } function App() { @@ -344,7 +380,11 @@ describe('useSWR - error', () => { } ) if (error) return
{error.message}
- return
<>hello, {data}
+ return ( +
+ <>hello, {data} +
+ ) } renderWithConfig() diff --git a/test/use-swr-infinite.test.tsx b/test/use-swr-infinite.test.tsx index 2e67c9b73..304008ea9 100644 --- a/test/use-swr-infinite.test.tsx +++ b/test/use-swr-infinite.test.tsx @@ -1183,7 +1183,7 @@ describe('useSWRInfinite', () => { await screen.findByText('data: B1,B2,B3') }) - it('should revalidate when the component is mounted and revalidateOnMount is enabled', async () => { + it('should revalidate the resource with bound mutate when arguments are passed', async () => { const key = createKey() let counter = 0 @@ -1223,6 +1223,71 @@ describe('useSWRInfinite', () => { await screen.findByText('data: 2') }) + // https://github.com/vercel/swr/issues/1899 + it('should revalidate the resource with bound mutate when options is of Object type ', async () => { + let t = 0 + const key = createKey() + const fetcher = jest.fn(async () => + createResponse(`foo-${t++}`, { delay: 10 }) + ) + const logger = [] + function Page() { + const { data, mutate } = useSWRInfinite(() => key, fetcher, { + dedupingInterval: 0 + }) + logger.push(data) + return ( + <> +
data: {String(data)}
+ + + ) + } + + renderWithConfig() + await screen.findByText('data: foo-0') + + fireEvent.click(screen.getByText('mutate')) + await screen.findByText('data: foo-1') + expect(fetcher).toBeCalledTimes(2) + + expect(logger).toEqual([undefined, ['foo-0'], ['foo-1']]) + }) + + // https://github.com/vercel/swr/issues/1899 + it('should not revalidate the resource with bound mutate when options is of Object type', async () => { + let t = 0 + const key = createKey() + const fetcher = jest.fn(async () => + createResponse(`foo-${t++}`, { delay: 10 }) + ) + const logger = [] + function Page() { + const { data, mutate } = useSWRInfinite(() => key, fetcher, { + dedupingInterval: 0 + }) + logger.push(data) + return ( + <> +
data: {String(data)}
+ + + ) + } + + renderWithConfig() + await screen.findByText('data: foo-0') + + fireEvent.click(screen.getByText('mutate')) + expect(fetcher).toBeCalledTimes(1) + + expect(logger).toEqual([undefined, ['foo-0']]) + }) + it('should share data with useSWR', async () => { const key = createKey() const SWR = () => { diff --git a/test/use-swr-suspense.test.tsx b/test/use-swr-suspense.test.tsx index 1f744c913..16cc788ad 100644 --- a/test/use-swr-suspense.test.tsx +++ b/test/use-swr-suspense.test.tsx @@ -16,7 +16,9 @@ import { sleep } from './utils' -class ErrorBoundary extends React.Component> { +class ErrorBoundary extends React.Component< + PropsWithChildren<{ fallback: ReactNode }> +> { state = { hasError: false } static getDerivedStateFromError() { return { @@ -112,9 +114,13 @@ describe('useSWR - suspense', () => { jest.spyOn(console, 'error').mockImplementation(() => {}) const key = createKey() function Section() { - const { data } = useSWR(key, () => createResponse(new Error('error')), { - suspense: true - }) + const { data } = useSWR( + key, + () => createResponse(new Error('error')), + { + suspense: true + } + ) return
{data}
}