File tree Expand file tree Collapse file tree 3 files changed +53
-2
lines changed Expand file tree Collapse file tree 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
129129See the [ json2mq docs] ( https://github.com/akiran/json2mq/blob/master/README.md#usage ) for more
130130examples of queries you can construct using objects.
131131
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+
132137If you're curious about how react-media differs from
133138[ react-responsive] ( https://github.com/contra/react-responsive ) , please see
134139[ 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 {
1414 PropTypes . arrayOf ( PropTypes . object . isRequired )
1515 ] ) . isRequired ,
1616 render : PropTypes . func ,
17- children : PropTypes . oneOfType ( [ PropTypes . node , PropTypes . func ] )
17+ children : PropTypes . oneOfType ( [ PropTypes . node , PropTypes . func ] ) ,
18+ targetWindow : PropTypes . object
1819 } ;
1920
2021 static defaultProps = {
@@ -31,10 +32,17 @@ class Media extends React.Component {
3132 if ( typeof window !== "object" ) return ;
3233
3334 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+ }
3442
3543 if ( typeof query !== "string" ) query = json2mq ( query ) ;
3644
37- this . mediaQueryList = window . matchMedia ( query ) ;
45+ this . mediaQueryList = targetWindow . matchMedia ( query ) ;
3846 this . mediaQueryList . addListener ( this . updateMatches ) ;
3947 this . updateMatches ( ) ;
4048 }
Original file line number Diff line number Diff line change @@ -122,6 +122,44 @@ describe("A <Media>", () => {
122122 } ) ;
123123 } ) ;
124124
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+
125163 describe ( "rendered on the server" , ( ) => {
126164 beforeEach ( ( ) => {
127165 window . matchMedia = createMockMediaMatcher ( true ) ;
You can’t perform that action at this time.
0 commit comments