-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
[material-ui] useMediaQuery('print') doesn't work when print started from window.print #17595
[material-ui] useMediaQuery('print') doesn't work when print started from window.print #17595
Comments
It seems that we should update the demo to remove the print use case. It's not working: https://bugzilla.mozilla.org/show_bug.cgi?id=774398 nor it will anytime soon. There is an interesting comment in this 7 years old thread, the spec doesn't mention which document it should listen to. Firefox creates a new one when it prints. |
Instead of print, we can mention dark mode preference or motion reduction preference in the docs. We can also warn about print not being supported well. cc @joshwooding. |
The issue is solved since Firefox 105: proof https://cxrdm.csb.app/. Once this version has enough adoption, we should remove: https://mui.com/material-ui/react-use-media-query/#basic-media-query. This will likely be once we update https://mui.com/material-ui/getting-started/supported-platforms/#browser for v6. Thank @ztoben for the heads-up in yocontra/react-responsive#246 (comment). |
We can now remove the docs mentioned, it's noise since thz minimum Firefox version support is v115 with Material UI v6 https://mui.com/material-ui/getting-started/supported-platforms/#browser |
Hi, I have been looking into how to resolve this issue.
Based on my investigation, the flow may look like this. flowchart LR
a["window.print()"] --> b[mediaQuery state set to true]
b --> c["Capture the screen and show 'print' dialog"]
b --> d["re-rendering"]
c --> e["'print' done"]
e --> f["mediaQuery state set to false"]
d --> f
f --> g["re-rendering"]
To help you understand the code base, I am sharing this code. import { Box, Button, useMediaQuery } from "@mui/material";
import { useEffect, useRef } from "react";
import "./styles.css";
export default function App() {
// === change element on media query "print" triggered ===>
const printingRef = useRef<HTMLHeadingElement>(document.createElement("h1"));
useEffect(() => {
const printMediaMatch = window.matchMedia("print");
const changeColor = () => {
if (printMediaMatch.matches) {
printingRef.current.style.color = "blue";
} else {
printingRef.current.style.color = "black";
}
};
printMediaMatch.addEventListener("change", changeColor);
return () => printMediaMatch.removeEventListener("change", changeColor);
}, []);
// <======
// Author's original code
const print = () => {
window.print();
};
const isPrintView = useMediaQuery("print");
return (
<div className="App">
<h1>This is visible always.</h1>
<Box displayPrint="none">
<h1>This is hidden with Box.</h1>
</Box>
{!isPrintView && <h1>This should be hidden with useMediaQuery.</h1>}
<h1 ref={printingRef}>This should be blue colored at printing.</h1>
<Button onClick={print}>Print via window.print</Button>
</div>
);
} The view changes correctly with the setting style on element directly, but 'useMediaQuery("print")' doesn't work properly. Giving it more operation enough to delay executing time for event callback, It won't work properly. codesandbox import { Box, Button, useMediaQuery } from "@mui/material";
import { useEffect, useRef } from "react";
import "./styles.css";
export default function App() {
// === change element on media query "print" triggered ===>
const printingRef = useRef<HTMLHeadingElement>(document.createElement("h1"));
useEffect(() => {
const printMediaMatch = window.matchMedia("print");
const changeColor = () => {
// delay excuting time
for (let i = 0; i < 9000000; i++) {
if (i % 2 == 0) {
printingRef.current.style.color = "red";
} else {
printingRef.current.style.color = "green";
}
}
if (printMediaMatch.matches) {
printingRef.current.style.color = "blue";
} else {
printingRef.current.style.color = "black";
}
};
printMediaMatch.addEventListener("change", changeColor);
return () => printMediaMatch.removeEventListener("change", changeColor);
}, []);
// <======
// Author's original code
const print = () => {
window.print();
};
const isPrintView = useMediaQuery("print");
return (
<div className="App">
<h1>This is visible always.</h1>
<Box displayPrint="none">
<h1>This is hidden with Box.</h1>
</Box>
{!isPrintView && <h1>This should be hidden with useMediaQuery.</h1>}
<h1 ref={printingRef}>This should be blue colored at printing.</h1>
<Button onClick={print}>Print via window.print</Button>
</div>
);
} In conclusion, here I have tasks to solve this issue.
|
Current Behavior 😯
Demo: https://codesandbox.io/embed/gifted-bohr-cxrdm
Chrome:
useMediaQuery('print')
matches only when print is started withCtrl+P
orPrint
chosen from browser's menu. When print is started fromwindow.print
method - it doesn't match. (See headings on sample.)Firefox:
useMediaQuery('print')
never matches.Expected Behavior 🤔
I expect to
useMediaQuery('print')
to match for all "printing situations", regardless it is started from "browser user action" or "programmatically". And it should work on Firefox in general.In attached demo - I expect to have "This should be hidden with useMediaQuery." paragraph to be hidden in all "printing situations".
Steps to Reproduce 🕹
See demo: https://codesandbox.io/embed/gifted-bohr-cxrdm
Try to print via browser (
Ctrl+P
orPrint
from main menu) or via button "print via window.print" to see how it behaves.Context 🔦
I'm trying to hide some elements for printing. Some blocks may be wrapped with
<Box displayPrint="none">
- and it works. Sometimes I need to have "lower level" flag determining if this is print view, so I want to utilizeuseMediaQuery('print')
- to avoid adding extradiv
s to DOM (whatBox
does).Your Environment 🌎
The text was updated successfully, but these errors were encountered: