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

[material-ui] useMediaQuery('print') doesn't work when print started from window.print #17595

Open
2 tasks done
robert-skarzycki opened this issue Sep 27, 2019 · 5 comments · Fixed by #17642 · May be fixed by #44790
Open
2 tasks done

[material-ui] useMediaQuery('print') doesn't work when print started from window.print #17595

robert-skarzycki opened this issue Sep 27, 2019 · 5 comments · Fixed by #17642 · May be fixed by #44790
Labels
docs Improvements or additions to the documentation external dependency Blocked by external dependency, we can’t do anything about it hook: useMediaQuery ready to take Help wanted. Guidance available. There is a high chance the change will be accepted

Comments

@robert-skarzycki
Copy link

  • 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 😯

Demo: https://codesandbox.io/embed/gifted-bohr-cxrdm

Chrome:
useMediaQuery('print') matches only when print is started with Ctrl+P or Print chosen from browser's menu. When print is started from window.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 or Print 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 utilize useMediaQuery('print') - to avoid adding extra divs to DOM (what Box does).

Your Environment 🌎

Tech Version
Material-UI v4.4.3
React 16.8.4
Browser Firefox 69.0.1, Chrome 77.0.3865.90
@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 27, 2019

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.

@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 27, 2019

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.

@oliviertassinari oliviertassinari added docs Improvements or additions to the documentation hook: useMediaQuery good first issue Great for first contributions. Enable to learn the contribution process. labels Sep 27, 2019
@joshwooding joshwooding added the hacktoberfest https://hacktoberfest.digitalocean.com/ label Sep 30, 2019
@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 22, 2022

The issue is solved since Firefox 105: proof https://cxrdm.csb.app/. Once this version has enough adoption, we should remove:

Screenshot 2022-09-22 at 15 13 12

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.

Screenshot 2022-09-22 at 15 14 05

Thank @ztoben for the heads-up in yocontra/react-responsive#246 (comment).

@oliviertassinari oliviertassinari added v6.x and removed good first issue Great for first contributions. Enable to learn the contribution process. hacktoberfest https://hacktoberfest.digitalocean.com/ labels Sep 22, 2022
@oliviertassinari oliviertassinari added the external dependency Blocked by external dependency, we can’t do anything about it label Sep 22, 2022
@samuelsycamore samuelsycamore changed the title useMediaQuery('print') doesn't work when print started from window.print [material-ui] useMediaQuery('print') doesn't work when print started from window.print Nov 28, 2023
@DiegoAndai DiegoAndai removed the v6.x label Dec 7, 2023
@DiegoAndai DiegoAndai added this to the Material UI: v7 draft milestone Dec 7, 2023
@oliviertassinari oliviertassinari removed this from the Material UI: v7 (draft) milestone Sep 29, 2024
@oliviertassinari oliviertassinari added the ready to take Help wanted. Guidance available. There is a high chance the change will be accepted label Sep 29, 2024
@oliviertassinari
Copy link
Member

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

@good-jinu
Copy link

good-jinu commented Dec 16, 2024

Hi, I have been looking into how to resolve this issue.

print makes new document for the copy of current document. so It is hard to make a change only when 'print'

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"]
Loading

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.

  • Remove You can't use 'print' per browsers limitation, for example Firefox. warning in docs.
  • add Using "print" as a parameter in useMediaQuery may not work properly. warning in docs
  • Show a console warning when using useMediaQuery with print query
    • Recommend using the event from the media query object returned by matchMedia('print') instead of useMediaQuery('print'). Don't recommend an other way, it may not work neither

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to the documentation external dependency Blocked by external dependency, we can’t do anything about it hook: useMediaQuery ready to take Help wanted. Guidance available. There is a high chance the change will be accepted
Projects
None yet
5 participants