Skip to content

Commit 1275f37

Browse files
authored
[utils] Fix "useId" & "useSyncExternalStore" imports to not be statically analysable (#43360)
1 parent 4852745 commit 1275f37

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

packages/mui-system/src/useMediaQuery/useMediaQuery.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface UseMediaQueryOptions {
3030
ssrMatchMedia?: (query: string) => { matches: boolean };
3131
}
3232

33+
// TODO React 17: Remove `useMediaQueryOld` once React 17 support is removed
3334
function useMediaQueryOld(
3435
query: string,
3536
defaultMatches: boolean,
@@ -71,8 +72,9 @@ function useMediaQueryOld(
7172
return match;
7273
}
7374

74-
// eslint-disable-next-line no-useless-concat -- Workaround for https://github.com/webpack/webpack/issues/14814
75-
const maybeReactUseSyncExternalStore: undefined | any = (React as any)['useSyncExternalStore' + ''];
75+
// See https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379 for why
76+
const safeReact = { ...React };
77+
const maybeReactUseSyncExternalStore: undefined | any = safeReact.useSyncExternalStore;
7678

7779
function useMediaQueryNew(
7880
query: string,
@@ -148,7 +150,6 @@ export default function useMediaQuery<Theme = unknown>(
148150
let query = typeof queryInput === 'function' ? queryInput(theme) : queryInput;
149151
query = query.replace(/^@media( ?)/m, '');
150152

151-
// TODO: Drop `useMediaQueryOld` and use `use-sync-external-store` shim in `useMediaQueryNew` once the package is stable
152153
const useMediaQueryImplementation =
153154
maybeReactUseSyncExternalStore !== undefined ? useMediaQueryNew : useMediaQueryOld;
154155
const match = useMediaQueryImplementation(

packages/mui-utils/src/useId/useId.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { expect } from 'chai';
33
import { createRenderer, screen } from '@mui/internal-test-utils';
4-
import useId from './useId';
4+
import useId from '@mui/utils/useId';
55

66
describe('useId', () => {
77
const { render, renderToString } = createRenderer();

packages/mui-utils/src/useId/useId.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import * as React from 'react';
33

44
let globalId = 0;
5+
6+
// TODO React 17: Remove `useGlobalId` once React 17 support is removed
57
function useGlobalId(idOverride?: string): string | undefined {
68
const [defaultId, setDefaultId] = React.useState(idOverride);
79
const id = idOverride || defaultId;
@@ -18,19 +20,23 @@ function useGlobalId(idOverride?: string): string | undefined {
1820
return id;
1921
}
2022

21-
// downstream bundlers may remove unnecessary concatenation, but won't remove toString call -- Workaround for https://github.com/webpack/webpack/issues/14814
22-
const maybeReactUseId: undefined | (() => string) = (React as any)['useId'.toString()];
23+
// See https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379 for why
24+
const safeReact = { ...React };
25+
const maybeReactUseId: undefined | (() => string) = safeReact.useId;
26+
2327
/**
2428
*
2529
* @example <div id={useId()} />
2630
* @param idOverride
2731
* @returns {string}
2832
*/
2933
export default function useId(idOverride?: string): string | undefined {
34+
// React.useId() is only available from React 17.0.0.
3035
if (maybeReactUseId !== undefined) {
3136
const reactId = maybeReactUseId();
3237
return idOverride ?? reactId;
3338
}
39+
3440
// TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
3541
// eslint-disable-next-line react-hooks/rules-of-hooks -- `React.useId` is invariant at runtime.
3642
return useGlobalId(idOverride);

0 commit comments

Comments
 (0)