@@ -24,31 +24,51 @@ class Media extends React.Component {
24
24
25
25
queries = [ ] ;
26
26
27
- state = {
28
- matches :
29
- this . props . defaultMatches ||
30
- Object . keys ( this . props . queries ) . reduce (
31
- ( acc , key ) => ( { ...acc , [ key ] : true } ) ,
32
- { }
33
- )
34
- } ;
27
+ constructor ( props ) {
28
+ super ( props ) ;
29
+
30
+ if ( typeof window !== "object" ) {
31
+ // In case we're rendering on the server
32
+ this . state = {
33
+ matches :
34
+ this . props . defaultMatches ||
35
+ Object . keys ( this . props . queries ) . reduce (
36
+ ( acc , key ) => ( { ...acc , [ key ] : true } ) ,
37
+ { }
38
+ )
39
+ } ;
40
+ return ;
41
+ }
35
42
36
- updateMatches = ( ) => {
37
- const newMatches = this . queries . reduce (
43
+ this . initialize ( ) ;
44
+
45
+ // Instead of calling this.updateMatches, we manually set the state to prevent
46
+ // calling setState, which could trigger an unnecessary second render
47
+ this . state = {
48
+ matches :
49
+ this . props . defaultMatches !== undefined
50
+ ? this . props . defaultMatches
51
+ : this . getMatches ( )
52
+ } ;
53
+ this . onChange ( ) ;
54
+ }
55
+
56
+ getMatches = ( ) => {
57
+ return this . queries . reduce (
38
58
( acc , { name, mqList } ) => ( { ...acc , [ name ] : mqList . matches } ) ,
39
59
{ }
40
60
) ;
41
- this . setState ( { matches : newMatches } ) ;
42
-
43
- const { onChange } = this . props ;
44
- if ( onChange ) {
45
- onChange ( newMatches ) ;
46
- }
47
61
} ;
48
62
49
- componentWillMount ( ) {
50
- if ( typeof window !== "object" ) return ;
63
+ updateMatches = ( ) => {
64
+ const newMatches = this . getMatches ( ) ;
51
65
66
+ this . setState ( ( ) => ( {
67
+ matches : newMatches
68
+ } ) , this . onChange ) ;
69
+ } ;
70
+
71
+ initialize ( ) {
52
72
const targetWindow = this . props . targetWindow || window ;
53
73
54
74
invariant (
@@ -67,8 +87,23 @@ class Media extends React.Component {
67
87
68
88
return { name, qs, mqList } ;
69
89
} ) ;
90
+ }
70
91
71
- this . updateMatches ( ) ;
92
+ componentDidMount ( ) {
93
+ this . initialize ( ) ;
94
+ // If props.defaultMatches has been set, ensure we trigger a two-pass render.
95
+ // This is useful for SSR with mismatching defaultMatches vs actual matches from window.matchMedia
96
+ // Details: https://github.com/ReactTraining/react-media/issues/81
97
+ if ( this . props . defaultMatches !== undefined ) {
98
+ this . updateMatches ( ) ;
99
+ }
100
+ }
101
+
102
+ onChange ( ) {
103
+ const { onChange } = this . props ;
104
+ if ( onChange ) {
105
+ onChange ( this . state . matches ) ;
106
+ }
72
107
}
73
108
74
109
componentWillUnmount ( ) {
0 commit comments