File tree 3 files changed +53
-2
lines changed
3 files changed +53
-2
lines changed Original file line number Diff line number Diff line change @@ -129,6 +129,11 @@ Keys of media query objects are camel-cased and numeric values automatically get
129
129
See the [ json2mq docs] ( https://github.com/akiran/json2mq/blob/master/README.md#usage ) for more
130
130
examples of queries you can construct using objects.
131
131
132
+ An optional ` targetWindow ` prop can be specified if you want the ` query ` to be
133
+ evaluated against a different window object than the one the code is running in.
134
+ This can be useful for example if you are rendering part of your component tree
135
+ to an iframe or [ a popup window] ( https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202 ) .
136
+
132
137
If you're curious about how react-media differs from
133
138
[ react-responsive] ( https://github.com/contra/react-responsive ) , please see
134
139
[ this comment] ( https://github.com/ReactTraining/react-media/issues/70#issuecomment-347774260 ) .
Original file line number Diff line number Diff line change @@ -14,7 +14,8 @@ class Media extends React.Component {
14
14
PropTypes . arrayOf ( PropTypes . object . isRequired )
15
15
] ) . isRequired ,
16
16
render : PropTypes . func ,
17
- children : PropTypes . oneOfType ( [ PropTypes . node , PropTypes . func ] )
17
+ children : PropTypes . oneOfType ( [ PropTypes . node , PropTypes . func ] ) ,
18
+ targetWindow : PropTypes . object
18
19
} ;
19
20
20
21
static defaultProps = {
@@ -31,10 +32,17 @@ class Media extends React.Component {
31
32
if ( typeof window !== "object" ) return ;
32
33
33
34
let { query } = this . props ;
35
+ const targetWindow = this . props . targetWindow || window ;
36
+
37
+ if ( ! targetWindow . matchMedia ) {
38
+ throw new Error (
39
+ 'You passed a `targetWindow` prop to `Media` that does not have a `matchMedia` function.'
40
+ ) ;
41
+ }
34
42
35
43
if ( typeof query !== "string" ) query = json2mq ( query ) ;
36
44
37
- this . mediaQueryList = window . matchMedia ( query ) ;
45
+ this . mediaQueryList = targetWindow . matchMedia ( query ) ;
38
46
this . mediaQueryList . addListener ( this . updateMatches ) ;
39
47
this . updateMatches ( ) ;
40
48
}
Original file line number Diff line number Diff line change @@ -122,6 +122,44 @@ describe("A <Media>", () => {
122
122
} ) ;
123
123
} ) ;
124
124
125
+ describe ( "when a custom targetWindow prop is passed" , ( ) => {
126
+ beforeEach ( ( ) => {
127
+ window . matchMedia = createMockMediaMatcher ( true ) ;
128
+ } ) ;
129
+
130
+ it ( "renders its child" , ( ) => {
131
+ const testWindow = {
132
+ matchMedia : createMockMediaMatcher ( false )
133
+ } ;
134
+
135
+ const element = (
136
+ < Media query = "" targetWindow = { testWindow } >
137
+ { matches => ( matches ? < div > hello</ div > : < div > goodbye</ div > ) }
138
+ </ Media >
139
+ ) ;
140
+
141
+ ReactDOM . render ( element , node , ( ) => {
142
+ expect ( node . firstChild . innerHTML ) . toMatch ( / g o o d b y e / ) ;
143
+ } ) ;
144
+ } ) ;
145
+
146
+ describe ( "when a non-window prop is passed for targetWindow" , ( ) => {
147
+ it ( "errors with a useful message" , ( ) => {
148
+ const notAWindow = { } ;
149
+
150
+ const element = (
151
+ < Media query = "" targetWindow = { notAWindow } >
152
+ { matches => ( matches ? < div > hello</ div > : < div > goodbye</ div > ) }
153
+ </ Media >
154
+ ) ;
155
+
156
+ expect ( ( ) => {
157
+ ReactDOM . render ( element , node , ( ) => { } ) ;
158
+ } ) . toThrow ( "does not have a `matchMedia` function" ) ;
159
+ } ) ;
160
+ } )
161
+ } ) ;
162
+
125
163
describe ( "rendered on the server" , ( ) => {
126
164
beforeEach ( ( ) => {
127
165
window . matchMedia = createMockMediaMatcher ( true ) ;
You can’t perform that action at this time.
0 commit comments