@@ -14,34 +14,44 @@ import useMediaQuery from '@mui/material/useMediaQuery';
1414import { ThemeProvider } from '@mui/material/styles' ;
1515
1616const usesUseSyncExternalStore = React . useSyncExternalStore !== undefined ;
17+ const matchMediaInstances = new Map ( ) ;
1718
18- function createMatchMedia ( width , ref ) {
19+ function createMatchMedia ( width ) {
1920 const listeners = [ ] ;
2021 return ( query ) => {
21- const instance = {
22- matches : mediaQuery . match ( query , {
23- width,
24- } ) ,
25- addEventListener : ( eventType , listener ) => {
26- listeners . push ( listener ) ;
27- } ,
28- removeEventListener : ( eventType , listener ) => {
29- const index = listeners . indexOf ( listener ) ;
30- if ( index > - 1 ) {
31- listeners . splice ( index , 1 ) ;
32- }
33- } ,
34- } ;
35- ref . push ( {
36- instance,
37- listeners,
38- } ) ;
22+ let instance = matchMediaInstances . get ( query ) ?. instance ;
23+
24+ if ( ! instance ) {
25+ instance = {
26+ matches : mediaQuery . match ( query , {
27+ width,
28+ } ) ,
29+ addEventListener : ( eventType , listener ) => {
30+ listeners . push ( listener ) ;
31+ } ,
32+ removeEventListener : ( eventType , listener ) => {
33+ const index = listeners . indexOf ( listener ) ;
34+ if ( index > - 1 ) {
35+ listeners . splice ( index , 1 ) ;
36+ }
37+ } ,
38+ } ;
39+ matchMediaInstances . set ( query , {
40+ instance,
41+ listeners,
42+ } ) ;
43+ }
44+
3945 return instance ;
4046 } ;
4147}
4248
4349describe ( 'useMediaQuery' , ( ) => {
44- const { render, renderToString } = createRenderer ( ) ;
50+ const { render, renderToString } = createRenderer ( { strict : true } ) ;
51+
52+ beforeEach ( ( ) => {
53+ matchMediaInstances . clear ( ) ;
54+ } ) ;
4555
4656 describe ( 'without window.matchMedia' , ( ) => {
4757 let originalMatchmedia ;
@@ -68,11 +78,8 @@ describe('useMediaQuery', () => {
6878 } ) ;
6979
7080 describe ( 'with window.matchMedia' , ( ) => {
71- let matchMediaInstances ;
72-
7381 beforeEach ( ( ) => {
74- matchMediaInstances = [ ] ;
75- const fakeMatchMedia = createMatchMedia ( 1200 , matchMediaInstances ) ;
82+ const fakeMatchMedia = createMatchMedia ( 1200 ) ;
7683 // can't stub nonexistent properties with sinon
7784 // jsdom does not implement window.matchMedia
7885 if ( window . matchMedia === undefined ) {
@@ -276,8 +283,9 @@ describe('useMediaQuery', () => {
276283 expect ( getRenderCountRef . current ( ) ) . to . equal ( usesUseSyncExternalStore ? 2 : 4 ) ;
277284 } ) ;
278285
279- it ( 'should observe the media query' , ( ) => {
286+ it ( 'should observe the media query' , async ( ) => {
280287 const getRenderCountRef = React . createRef ( ) ;
288+ const query = '(min-width:2000px)' ;
281289 function Test ( props ) {
282290 const matches = useMediaQuery ( props . query ) ;
283291
@@ -291,14 +299,16 @@ describe('useMediaQuery', () => {
291299 query : PropTypes . string . isRequired ,
292300 } ;
293301
294- render ( < Test query = "(min-width:2000px)" /> ) ;
302+ render ( < Test query = { query } /> ) ;
303+
295304 expect ( getRenderCountRef . current ( ) ) . to . equal ( 1 ) ;
296305 expect ( screen . getByTestId ( 'matches' ) . textContent ) . to . equal ( 'false' ) ;
297306
298- act ( ( ) => {
299- matchMediaInstances [ matchMediaInstances . length - 1 ] . instance . matches = true ;
300- matchMediaInstances [ matchMediaInstances . length - 1 ] . listeners [ 0 ] ( ) ;
307+ await act ( async ( ) => {
308+ matchMediaInstances . get ( query ) . instance . matches = true ;
309+ matchMediaInstances . get ( query ) . listeners [ 0 ] ( ) ;
301310 } ) ;
311+
302312 expect ( screen . getByTestId ( 'matches' ) . textContent ) . to . equal ( 'true' ) ;
303313 expect ( getRenderCountRef . current ( ) ) . to . equal ( 2 ) ;
304314 } ) ;
0 commit comments