diff --git a/src/_internal/types.ts b/src/_internal/types.ts index 528dae932..5ec850658 100644 --- a/src/_internal/types.ts +++ b/src/_internal/types.ts @@ -466,7 +466,7 @@ type SWRConfigurationWithOptionalFallback = ? Omit & Pick, 'fallbackData'> : Options -export interface SWRResponse { +export interface SWRBaseResponse { /** * The returned data of the fetcher function. */ @@ -478,8 +478,25 @@ export interface SWRResponse { mutate: KeyedMutator isValidating: boolean isLoading: IsLoadingResponse + /** + * A derived boolean from {@link isLoading} and {@link error} which indicates if the request has completed successfully. + */ + isSuccess: boolean +} +export interface SWRSuccessResponse + extends SWRBaseResponse { + data: Data + isSuccess: true +} +export interface SWRErrorResponse + extends SWRBaseResponse { + error: Error + isSuccess: false } +export type SWRResponse = + | SWRSuccessResponse + | SWRErrorResponse export type KeyLoader = | ((index: number, previousPageData: any | null) => Args) | null diff --git a/src/index/use-swr.ts b/src/index/use-swr.ts index 98ef34f1f..bad823efc 100644 --- a/src/index/use-swr.ts +++ b/src/index/use-swr.ts @@ -746,6 +746,11 @@ export const useSWRHandler = ( get isLoading() { stateDependencies.isLoading = true return isLoading + }, + get isSuccess() { + stateDependencies.isLoading = true + stateDependencies.error = true + return !isLoading && isUndefined(error) } } as SWRResponse } diff --git a/test/type/isSuccess.tsx b/test/type/isSuccess.tsx new file mode 100644 index 000000000..321431235 --- /dev/null +++ b/test/type/isSuccess.tsx @@ -0,0 +1,12 @@ +import useSWR from 'swr' +import { expectType } from './utils' + +export function useIsSuccess() { + const fetcherResult = 'helloWorld' + const { data, isSuccess } = useSWR('key', () => fetcherResult) + expectType(fetcherResult) + expectType(undefined) + if (isSuccess) { + expectType(fetcherResult) + } +}