Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[useMediaQuery] Iframe support #18694

Closed
2 tasks done
oliviertassinari opened this issue Dec 5, 2019 · 3 comments · Fixed by #18741
Closed
2 tasks done

[useMediaQuery] Iframe support #18694

oliviertassinari opened this issue Dec 5, 2019 · 3 comments · Fixed by #18741
Labels
bug 🐛 Something doesn't work good first issue Great for first contributions. Enable to learn the contribution process. hook: useMediaQuery

Comments

@oliviertassinari
Copy link
Member

oliviertassinari commented Dec 5, 2019

  • The issue is present in the latest release.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

When using react-frame-component to render useMediaQuery in an iframe, the media query is relative to the parent window, not the nested frame.

Expected Behavior 🤔

It should be possible to use the component with the contentWindow of the iframe.

Steps to Reproduce 🕹

Steps:

  1. Open /docs/src/pages/components/app-bar/BottomAppBar.tsx
  2. Edit it the demo with:
import React from 'react';
import useMediaQuery from '@material-ui/core/useMediaQuery';

export default function SimpleMediaQuery(props) {
  const matches = useMediaQuery('(min-width:600px)');

  return <span>{`(min-width:600px) matches: ${matches}`}</span>;
}
  1. Open the page (http://0.0.0.0:3000/components/app-bar) and resize the window to 700px.
  2. It shouldn't match, the iframe is below 600px, but the parent window is above.

Context 🔦

The issue was first reported by @siriwatknp on Twitter.

Your Environment 🌎

Tech Version
Material-UI v4.7.1
@oliviertassinari oliviertassinari added bug 🐛 Something doesn't work good first issue Great for first contributions. Enable to learn the contribution process. hook: useMediaQuery labels Dec 5, 2019
@oliviertassinari
Copy link
Member Author

I believe we could solve the problem with:

diff --git a/docs/src/pages/components/use-media-query/use-media-query.md b/docs/src/pages/components/use-media-query/use-media-query.md
index 51f68bca3..dd06c96c9 100644
--- a/docs/src/pages/components/use-media-query/use-media-query.md
+++ b/docs/src/pages/components/use-media-query/use-media-query.md
@@ -162,12 +162,13 @@ You can reproduce the same behavior with a `useWidth` hook:
   - `options.defaultMatches` (*Boolean* [optional]):
   As `window.matchMedia()` is unavailable on the server,
   we return a default matches during the first mount. The default value is `false`.
+  - `options.matchMedia` (*Function* [optional]) You can provide your own implementation of *matchMedia*. This especially useful for handling an iframe content window.
   - `options.noSsr` (*Boolean* [optional]): Defaults to `false`.
   In order to perform the server-side rendering reconciliation, it needs to render twice.
   A first time with nothing and a second time with the children.
   This double pass rendering cycle comes with a drawback. It's slower.
   You can set this flag to `true` if you are **not doing server-side rendering**.
-  - `options.ssrMatchMedia` (*Function* [optional]) You can provide your own implementation of *matchMedia*. This especially useful for [server-side rendering support](#server-side-rendering).
+  - `options.ssrMatchMedia` (*Function* [optional]) You can provide your own implementation of *matchMedia* in a [server-side rendering context](#server-side-rendering).

 Note: You can change the default options using the [`default props`](/customization/globals/#default-props) feature of the theme with the `MuiUseMediaQuery` key.

diff --git a/packages/material-ui/src/useMediaQuery/useMediaQuery.js b/packages/material-ui/src/useMediaQuery/useMediaQuery.js
index e969caa2f..b17054efe 100644
--- a/packages/material-ui/src/useMediaQuery/useMediaQuery.js
+++ b/packages/material-ui/src/useMediaQuery/useMediaQuery.js
@@ -34,14 +34,19 @@ function useMediaQuery(queryInput, options = {}) {
   const supportMatchMedia =
     typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined';

-  const { defaultMatches = false, noSsr = false, ssrMatchMedia = null } = {
+  const {
+    defaultMatches = false,
+    matchMedia = supportMatchMedia ? window.matchMedia : null,
+    noSsr = false,
+    ssrMatchMedia = null,
+  } = {
     ...props,
     ...options,
   };

   const [match, setMatch] = React.useState(() => {
     if ((hydrationCompleted || noSsr) && supportMatchMedia) {
-      return window.matchMedia(query).matches;
+      return matchMedia(query).matches;
     }
     if (ssrMatchMedia) {
       return ssrMatchMedia(query).matches;
@@ -60,7 +65,7 @@ function useMediaQuery(queryInput, options = {}) {
       return undefined;
     }

-    const queryList = window.matchMedia(query);
+    const queryList = matchMedia(query);
     const updateMatch = () => {
       // Workaround Safari wrong implementation of matchMedia
       // TODO can we remove it?

So people can use it like this:

import React from 'react';
import useMediaQuery from '@material-ui/core/useMediaQuery';

export default function SimpleMediaQuery(props) {
  console.log('props.window.matchMedia');
  const matches = useMediaQuery('(min-width:600px)', { matchMedia: props.window().matchMedia });

  return <span>{`(min-width:600px) matches: ${matches}`}</span>;
}

@siriwatknp
Copy link
Member

Sounds good, will send PR soon.

@oliviertassinari
Copy link
Member Author

@siriwatknp Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work good first issue Great for first contributions. Enable to learn the contribution process. hook: useMediaQuery
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants