From 9293ec4724bcbc98df9886e028b98c97dc0a0a95 Mon Sep 17 00:00:00 2001 From: Tyler Dixon Date: Wed, 8 Jul 2026 14:31:28 -0700 Subject: [PATCH 1/7] fix: replace JSX.Element with React.ReactElement for React 19 compat JSX.Element was removed from the global JSX namespace in React 19 types. Components returning JSX.Element are no longer assignable to the updated ReactNode return type, causing type errors for users on React 19. Fixes #637 --- src/auth.tsx | 2 +- src/performance.tsx | 2 +- src/sdk.tsx | 2 +- src/storage.tsx | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/auth.tsx b/src/auth.tsx index d535b894..267ffd4d 100644 --- a/src/auth.tsx +++ b/src/auth.tsx @@ -244,7 +244,7 @@ export function ClaimsCheck({ user, fallback, children, requiredClaims }: Claims * * Meant for Concurrent mode only (``). [More detail](https://github.com/FirebaseExtended/reactfire/issues/325#issuecomment-827654376). */ -export function AuthCheck({ fallback, children, requiredClaims }: AuthCheckProps): JSX.Element { +export function AuthCheck({ fallback, children, requiredClaims }: AuthCheckProps): React.ReactElement { const { data: user } = useUser(); const suspenseMode = useSuspenseEnabledFromConfigAndContext(); diff --git a/src/performance.tsx b/src/performance.tsx index 78a0455c..7f444bae 100644 --- a/src/performance.tsx +++ b/src/performance.tsx @@ -6,7 +6,7 @@ export interface SuspensePerfProps { fallback: React.ReactNode; } -export function SuspenseWithPerf({ children, traceId, fallback }: SuspensePerfProps): JSX.Element { +export function SuspenseWithPerf({ children, traceId, fallback }: SuspensePerfProps): React.ReactElement { // TODO: Should this import firebase/performance? const perf = typeof globalThis !== 'undefined' ? globalThis.performance : undefined; diff --git a/src/sdk.tsx b/src/sdk.tsx index 2e7af1a6..ee66ffff 100644 --- a/src/sdk.tsx +++ b/src/sdk.tsx @@ -28,7 +28,7 @@ export const RemoteConfigSdkContext = React.createContext(SdkContext: React.Context) { - return function SdkProvider(props: React.PropsWithChildren<{ sdk: Sdk }>) { + return function SdkProvider(props: React.PropsWithChildren<{ sdk: Sdk }>): React.ReactElement { if (!props.sdk) throw new Error('no sdk provided'); const contextualAppName = useFirebaseApp().name; diff --git a/src/storage.tsx b/src/storage.tsx index 90ea56c1..fa76d756 100644 --- a/src/storage.tsx +++ b/src/storage.tsx @@ -37,7 +37,7 @@ export type StorageImageProps = { storagePath: string; storage?: FirebaseStorage; suspense?: boolean; - placeHolder?: JSX.Element; + placeHolder?: React.ReactElement; }; function StorageFromContext(props: StorageImageProps & React.DetailedHTMLProps, HTMLImageElement>) { @@ -48,7 +48,7 @@ function StorageFromContext(props: StorageImageProps & React.DetailedHTMLProps; } -function INTERNALStorageImage(props: StorageImageProps & React.DetailedHTMLProps, HTMLImageElement>): JSX.Element { +function INTERNALStorageImage(props: StorageImageProps & React.DetailedHTMLProps, HTMLImageElement>): React.ReactElement { const { storage, storagePath, suspense, placeHolder, ...imgProps } = props; const reactfireOptions: ReactFireOptions = { From 9d7300e86866c80faad612cb0376e8149fcfd33c Mon Sep 17 00:00:00 2001 From: Tyler Reitz Date: Thu, 9 Jul 2026 14:17:12 -0700 Subject: [PATCH 2/7] Update src/storage.tsx Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/storage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage.tsx b/src/storage.tsx index fa76d756..ded4b179 100644 --- a/src/storage.tsx +++ b/src/storage.tsx @@ -37,7 +37,7 @@ export type StorageImageProps = { storagePath: string; storage?: FirebaseStorage; suspense?: boolean; - placeHolder?: React.ReactElement; + placeHolder?: React.ReactNode; }; function StorageFromContext(props: StorageImageProps & React.DetailedHTMLProps, HTMLImageElement>) { From e292f1314f31f5e84b0d92e1b48c508e250ee115 Mon Sep 17 00:00:00 2001 From: Tyler Reitz Date: Thu, 9 Jul 2026 14:17:24 -0700 Subject: [PATCH 3/7] Update src/storage.tsx Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/storage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage.tsx b/src/storage.tsx index ded4b179..5a0299da 100644 --- a/src/storage.tsx +++ b/src/storage.tsx @@ -48,7 +48,7 @@ function StorageFromContext(props: StorageImageProps & React.DetailedHTMLProps; } -function INTERNALStorageImage(props: StorageImageProps & React.DetailedHTMLProps, HTMLImageElement>): React.ReactElement { +function INTERNALStorageImage(props: StorageImageProps & React.DetailedHTMLProps, HTMLImageElement>): React.ReactNode { const { storage, storagePath, suspense, placeHolder, ...imgProps } = props; const reactfireOptions: ReactFireOptions = { From 4121709f8a5f96ff7a787a2311af5667fb54eac1 Mon Sep 17 00:00:00 2001 From: Tyler Dixon Date: Thu, 9 Jul 2026 14:20:29 -0700 Subject: [PATCH 4/7] docs: regenerate API reference after React 19 type fixes --- docs/reference/functions/AuthCheck.md | 4 ++-- docs/reference/functions/SuspenseWithPerf.md | 4 ++-- docs/reference/interfaces/ObservableStatusSuccess.md | 8 ++++---- docs/reference/type-aliases/StorageImageProps.md | 2 +- docs/reference/variables/AnalyticsProvider.md | 4 ++-- docs/reference/variables/AppCheckProvider.md | 4 ++-- docs/reference/variables/AuthProvider.md | 4 ++-- docs/reference/variables/DatabaseProvider.md | 4 ++-- docs/reference/variables/FirestoreProvider.md | 4 ++-- docs/reference/variables/FunctionsProvider.md | 4 ++-- docs/reference/variables/PerformanceProvider.md | 4 ++-- docs/reference/variables/RemoteConfigProvider.md | 4 ++-- docs/reference/variables/StorageProvider.md | 4 ++-- 13 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/reference/functions/AuthCheck.md b/docs/reference/functions/AuthCheck.md index 9bedbb15..aa03a2be 100644 --- a/docs/reference/functions/AuthCheck.md +++ b/docs/reference/functions/AuthCheck.md @@ -6,7 +6,7 @@ # ~~Function: AuthCheck()~~ -> **AuthCheck**(`__namedParameters`): `Element` +> **AuthCheck**(`__namedParameters`): `ReactElement` Defined in: [src/auth.tsx:247](https://github.com/FirebaseExtended/reactfire/blob/main/src/auth.tsx#L247) @@ -18,7 +18,7 @@ Defined in: [src/auth.tsx:247](https://github.com/FirebaseExtended/reactfire/blo ## Returns -`Element` +`ReactElement` ## Deprecated diff --git a/docs/reference/functions/SuspenseWithPerf.md b/docs/reference/functions/SuspenseWithPerf.md index ea4a1e9d..6ab06a72 100644 --- a/docs/reference/functions/SuspenseWithPerf.md +++ b/docs/reference/functions/SuspenseWithPerf.md @@ -6,7 +6,7 @@ # Function: SuspenseWithPerf() -> **SuspenseWithPerf**(`__namedParameters`): `Element` +> **SuspenseWithPerf**(`__namedParameters`): `ReactElement` Defined in: [src/performance.tsx:9](https://github.com/FirebaseExtended/reactfire/blob/main/src/performance.tsx#L9) @@ -18,4 +18,4 @@ Defined in: [src/performance.tsx:9](https://github.com/FirebaseExtended/reactfir ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/interfaces/ObservableStatusSuccess.md b/docs/reference/interfaces/ObservableStatusSuccess.md index 8a5a4445..963adad4 100644 --- a/docs/reference/interfaces/ObservableStatusSuccess.md +++ b/docs/reference/interfaces/ObservableStatusSuccess.md @@ -46,7 +46,7 @@ Any error that may have occurred in the underlying observable #### Inherited from -`ObservableStatusBase.error` +[`ObservableStatusLoading`](ObservableStatusLoading.md).[`error`](ObservableStatusLoading.md#error) *** @@ -60,7 +60,7 @@ Promise that resolves after first emit from observable #### Inherited from -`ObservableStatusBase.firstValuePromise` +[`ObservableStatusError`](ObservableStatusError.md).[`firstValuePromise`](ObservableStatusError.md#firstvaluepromise) *** @@ -76,7 +76,7 @@ If `initialData` is passed in, this will be `true`. #### Inherited from -`ObservableStatusBase.hasEmitted` +[`ObservableStatusError`](ObservableStatusError.md).[`hasEmitted`](ObservableStatusError.md#hasemitted) *** @@ -90,7 +90,7 @@ If this is `true`, the hook will be emitting no further items. #### Inherited from -`ObservableStatusBase.isComplete` +[`ObservableStatusLoading`](ObservableStatusLoading.md).[`isComplete`](ObservableStatusLoading.md#iscomplete) *** diff --git a/docs/reference/type-aliases/StorageImageProps.md b/docs/reference/type-aliases/StorageImageProps.md index 5fd6a740..b75fa337 100644 --- a/docs/reference/type-aliases/StorageImageProps.md +++ b/docs/reference/type-aliases/StorageImageProps.md @@ -14,7 +14,7 @@ Defined in: [src/storage.tsx:36](https://github.com/FirebaseExtended/reactfire/b ### placeHolder? -> `optional` **placeHolder?**: `JSX.Element` +> `optional` **placeHolder?**: `React.ReactNode` Defined in: [src/storage.tsx:40](https://github.com/FirebaseExtended/reactfire/blob/main/src/storage.tsx#L40) diff --git a/docs/reference/variables/AnalyticsProvider.md b/docs/reference/variables/AnalyticsProvider.md index 1e51416e..67edf246 100644 --- a/docs/reference/variables/AnalyticsProvider.md +++ b/docs/reference/variables/AnalyticsProvider.md @@ -6,7 +6,7 @@ # Variable: AnalyticsProvider -> `const` **AnalyticsProvider**: (`props`) => `Element` +> `const` **AnalyticsProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:74](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L74) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:74](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/AppCheckProvider.md b/docs/reference/variables/AppCheckProvider.md index dd717bde..ff42596a 100644 --- a/docs/reference/variables/AppCheckProvider.md +++ b/docs/reference/variables/AppCheckProvider.md @@ -6,7 +6,7 @@ # Variable: AppCheckProvider -> `const` **AppCheckProvider**: (`props`) => `Element` +> `const` **AppCheckProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:72](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L72) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:72](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/AuthProvider.md b/docs/reference/variables/AuthProvider.md index 47de1c97..11ea5392 100644 --- a/docs/reference/variables/AuthProvider.md +++ b/docs/reference/variables/AuthProvider.md @@ -6,7 +6,7 @@ # Variable: AuthProvider -> `const` **AuthProvider**: (`props`) => `Element` +> `const` **AuthProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:73](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L73) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:73](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/DatabaseProvider.md b/docs/reference/variables/DatabaseProvider.md index c2a3a7e7..e8069948 100644 --- a/docs/reference/variables/DatabaseProvider.md +++ b/docs/reference/variables/DatabaseProvider.md @@ -6,7 +6,7 @@ # Variable: DatabaseProvider -> `const` **DatabaseProvider**: (`props`) => `Element` +> `const` **DatabaseProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:75](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L75) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:75](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/FirestoreProvider.md b/docs/reference/variables/FirestoreProvider.md index 6e680dcf..d689f31f 100644 --- a/docs/reference/variables/FirestoreProvider.md +++ b/docs/reference/variables/FirestoreProvider.md @@ -6,7 +6,7 @@ # Variable: FirestoreProvider -> `const` **FirestoreProvider**: (`props`) => `Element` +> `const` **FirestoreProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:76](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L76) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:76](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/FunctionsProvider.md b/docs/reference/variables/FunctionsProvider.md index 0557ac83..918b2609 100644 --- a/docs/reference/variables/FunctionsProvider.md +++ b/docs/reference/variables/FunctionsProvider.md @@ -6,7 +6,7 @@ # Variable: FunctionsProvider -> `const` **FunctionsProvider**: (`props`) => `Element` +> `const` **FunctionsProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:77](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L77) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:77](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/PerformanceProvider.md b/docs/reference/variables/PerformanceProvider.md index ef926f29..ee2fcc28 100644 --- a/docs/reference/variables/PerformanceProvider.md +++ b/docs/reference/variables/PerformanceProvider.md @@ -6,7 +6,7 @@ # Variable: PerformanceProvider -> `const` **PerformanceProvider**: (`props`) => `Element` +> `const` **PerformanceProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:78](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L78) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:78](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/RemoteConfigProvider.md b/docs/reference/variables/RemoteConfigProvider.md index 071b8e4c..8d3d3625 100644 --- a/docs/reference/variables/RemoteConfigProvider.md +++ b/docs/reference/variables/RemoteConfigProvider.md @@ -6,7 +6,7 @@ # Variable: RemoteConfigProvider -> `const` **RemoteConfigProvider**: (`props`) => `Element` +> `const` **RemoteConfigProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:80](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L80) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:80](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` diff --git a/docs/reference/variables/StorageProvider.md b/docs/reference/variables/StorageProvider.md index f558ec1c..dbcb81c1 100644 --- a/docs/reference/variables/StorageProvider.md +++ b/docs/reference/variables/StorageProvider.md @@ -6,7 +6,7 @@ # Variable: StorageProvider -> `const` **StorageProvider**: (`props`) => `Element` +> `const` **StorageProvider**: (`props`) => `ReactElement` Defined in: [src/sdk.tsx:79](https://github.com/FirebaseExtended/reactfire/blob/main/src/sdk.tsx#L79) @@ -18,4 +18,4 @@ Defined in: [src/sdk.tsx:79](https://github.com/FirebaseExtended/reactfire/blob/ ## Returns -`Element` +`ReactElement` From abd72c9b8e6a647aa898a743bd616a7c6cf89475 Mon Sep 17 00:00:00 2001 From: Tyler Dixon Date: Thu, 9 Jul 2026 14:24:25 -0700 Subject: [PATCH 5/7] ci: trigger checks From f2e84e8c2f40acacb2f5dc52a46d28daa3efc25f Mon Sep 17 00:00:00 2001 From: Tyler Dixon Date: Thu, 9 Jul 2026 14:26:47 -0700 Subject: [PATCH 6/7] docs: regenerate API reference without skipErrorChecking flag --- docs/reference/interfaces/ObservableStatusSuccess.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/interfaces/ObservableStatusSuccess.md b/docs/reference/interfaces/ObservableStatusSuccess.md index 963adad4..8a5a4445 100644 --- a/docs/reference/interfaces/ObservableStatusSuccess.md +++ b/docs/reference/interfaces/ObservableStatusSuccess.md @@ -46,7 +46,7 @@ Any error that may have occurred in the underlying observable #### Inherited from -[`ObservableStatusLoading`](ObservableStatusLoading.md).[`error`](ObservableStatusLoading.md#error) +`ObservableStatusBase.error` *** @@ -60,7 +60,7 @@ Promise that resolves after first emit from observable #### Inherited from -[`ObservableStatusError`](ObservableStatusError.md).[`firstValuePromise`](ObservableStatusError.md#firstvaluepromise) +`ObservableStatusBase.firstValuePromise` *** @@ -76,7 +76,7 @@ If `initialData` is passed in, this will be `true`. #### Inherited from -[`ObservableStatusError`](ObservableStatusError.md).[`hasEmitted`](ObservableStatusError.md#hasemitted) +`ObservableStatusBase.hasEmitted` *** @@ -90,7 +90,7 @@ If this is `true`, the hook will be emitting no further items. #### Inherited from -[`ObservableStatusLoading`](ObservableStatusLoading.md).[`isComplete`](ObservableStatusLoading.md#iscomplete) +`ObservableStatusBase.isComplete` *** From c2c2252c0ba0b96d7c9a4a4af39eaa6ef5b88326 Mon Sep 17 00:00:00 2001 From: Tyler Dixon Date: Fri, 10 Jul 2026 10:46:20 -0700 Subject: [PATCH 7/7] ci: add React 18/19 type-check matrix job --- .github/workflows/test.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 73d40756..d1cc2244 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -79,6 +79,27 @@ jobs: ./reactfire-${{ github.run_id }}/unpack.sh - name: Run tests run: npm run test + type-check: + runs-on: ubuntu-latest + strategy: + matrix: + react: ["18", "19"] + fail-fast: false + name: Type check (React ${{ matrix.react }}) + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: '24' + cache: 'npm' + - name: Install deps + run: npm ci + - name: Install React ${{ matrix.react }} types + run: npm install --no-save react@${{ matrix.react }} react-dom@${{ matrix.react }} @types/react@${{ matrix.react }} @types/react-dom@${{ matrix.react }} + - name: Type check + run: npx tsc --noEmit publish: runs-on: ubuntu-latest name: Publish (NPM)