diff --git a/packages/react-router/src/awaited.tsx b/packages/react-router/src/awaited.tsx index 31b689373b..c3397bd433 100644 --- a/packages/react-router/src/awaited.tsx +++ b/packages/react-router/src/awaited.tsx @@ -1,6 +1,7 @@ import * as React from 'react' import { TSR_DEFERRED_PROMISE, defer } from '@tanstack/router-core' +import { reactUse } from './utils' export type AwaitOptions = { promise: Promise @@ -8,9 +9,8 @@ export type AwaitOptions = { /** Suspend until a deferred promise resolves or rejects and return its data. */ export function useAwaited({ promise: _promise }: AwaitOptions): T { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (React.use) { - const data = React.use(_promise) + if (reactUse) { + const data = reactUse(_promise) return data } const promise = defer(_promise) diff --git a/packages/react-router/src/lazyRouteComponent.tsx b/packages/react-router/src/lazyRouteComponent.tsx index 71bba8e03e..b4fe8703c5 100644 --- a/packages/react-router/src/lazyRouteComponent.tsx +++ b/packages/react-router/src/lazyRouteComponent.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import { isModuleNotFoundError } from '@tanstack/router-core' +import { reactUse } from './utils' import type { AsyncRouteComponent } from './route' /** @@ -79,9 +80,8 @@ export function lazyRouteComponent< } if (!comp) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (React.use) { - React.use(load()) + if (reactUse) { + reactUse(load()) } else { throw load() } diff --git a/packages/react-router/src/utils.ts b/packages/react-router/src/utils.ts index 23443dc58e..33f8ea9acc 100644 --- a/packages/react-router/src/utils.ts +++ b/packages/react-router/src/utils.ts @@ -1,5 +1,19 @@ import * as React from 'react' +// Safe version of React.use() that will not cause compilation errors against +// React 18 with Webpack, which statically analyzes imports and fails when it +// sees React.use referenced (since 'use' is not exported from React 18). +// This uses a dynamic string lookup to avoid the static analysis. +const REACT_USE = 'use' + +/** + * React.use if available (React 19+), undefined otherwise. + * Use dynamic lookup to avoid Webpack compilation errors with React 18. + */ +export const reactUse: + | ((usable: Promise | React.Context) => T) + | undefined = (React as any)[REACT_USE] + export function useStableCallback) => any>( fn: T, ): T {