Skip to content

Commit

Permalink
[utils] Fix "useId" & "useSyncExternalStore" imports to not be static…
Browse files Browse the repository at this point in the history
…ally analysable (#43360)
  • Loading branch information
yash49 authored Sep 17, 2024
1 parent 4852745 commit 1275f37
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 6 deletions.
7 changes: 4 additions & 3 deletions packages/mui-system/src/useMediaQuery/useMediaQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface UseMediaQueryOptions {
ssrMatchMedia?: (query: string) => { matches: boolean };
}

// TODO React 17: Remove `useMediaQueryOld` once React 17 support is removed
function useMediaQueryOld(
query: string,
defaultMatches: boolean,
Expand Down Expand Up @@ -71,8 +72,9 @@ function useMediaQueryOld(
return match;
}

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

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

// TODO: Drop `useMediaQueryOld` and use `use-sync-external-store` shim in `useMediaQueryNew` once the package is stable
const useMediaQueryImplementation =
maybeReactUseSyncExternalStore !== undefined ? useMediaQueryNew : useMediaQueryOld;
const match = useMediaQueryImplementation(
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-utils/src/useId/useId.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { expect } from 'chai';
import { createRenderer, screen } from '@mui/internal-test-utils';
import useId from './useId';
import useId from '@mui/utils/useId';

describe('useId', () => {
const { render, renderToString } = createRenderer();
Expand Down
10 changes: 8 additions & 2 deletions packages/mui-utils/src/useId/useId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import * as React from 'react';

let globalId = 0;

// TODO React 17: Remove `useGlobalId` once React 17 support is removed
function useGlobalId(idOverride?: string): string | undefined {
const [defaultId, setDefaultId] = React.useState(idOverride);
const id = idOverride || defaultId;
Expand All @@ -18,19 +20,23 @@ function useGlobalId(idOverride?: string): string | undefined {
return id;
}

// downstream bundlers may remove unnecessary concatenation, but won't remove toString call -- Workaround for https://github.com/webpack/webpack/issues/14814
const maybeReactUseId: undefined | (() => string) = (React as any)['useId'.toString()];
// See https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379 for why
const safeReact = { ...React };
const maybeReactUseId: undefined | (() => string) = safeReact.useId;

/**
*
* @example <div id={useId()} />
* @param idOverride
* @returns {string}
*/
export default function useId(idOverride?: string): string | undefined {
// React.useId() is only available from React 17.0.0.
if (maybeReactUseId !== undefined) {
const reactId = maybeReactUseId();
return idOverride ?? reactId;
}

// TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
// eslint-disable-next-line react-hooks/rules-of-hooks -- `React.useId` is invariant at runtime.
return useGlobalId(idOverride);
Expand Down

0 comments on commit 1275f37

Please sign in to comment.