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

Problem with window.matchMedia API and window.print #11876

Closed
AlexanderLukin opened this issue Dec 18, 2017 · 8 comments
Closed

Problem with window.matchMedia API and window.print #11876

AlexanderLukin opened this issue Dec 18, 2017 · 8 comments

Comments

@AlexanderLukin
Copy link

I encountered a problem when I try to conditionally render content for "screen" and "print" media types using matchMedia API
https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia

In the latest Google Chrome for Windows 10, the content intended for "print" media type is displayed incorrectly in printout preview.

I created a minimal demo that shows the issue
https://codesandbox.io/s/q96rvrx2z9

In the first case, please, open the page and press "Ctrl + P" keys to open printout preview. In the console, you can see that updateComponent() function is called two times (one for printout preview and the second for the main page that overlapped by the printout preview I guess). In this case, everything is working correctly: in the printout, we can see "Print" word, and on the main screen "Screen" word is displayed even after closing the preview.

In the second case, please, try to open printout preview by clicking the "Screen" label. You can see that print() and updateComponetn() functions are called, but they don't force component rerendering as they should. Hence, we see "Screen" on the printout preview, but the "Print" label should be displayed.

Please, take a look when you have time.

@AlexanderLukin
Copy link
Author

This also associated with this issue
yocontra/react-responsive#137

@gaearon
Copy link
Collaborator

gaearon commented Dec 18, 2017

We use the issue tracker for bugs in React itself. What makes you think this is a React problem? It doesn’t use either of these APIs itself.

@AlexanderLukin
Copy link
Author

@gaearon Please, look at my first example
https://codesandbox.io/s/q96rvrx2z9

There are no any side dependencies there, only React itself.
I posted the link to react-responsive repo just to document out where this issue appeared the first time.

@gaearon
Copy link
Collaborator

gaearon commented Dec 18, 2017

Still, I don’t understand what the example is meant to demonstrate.

If the issue is specific to matchMedia API I can assure you React doesn’t do anything special that would break it. So your question would be easier to answer without React. Can you create a React-less example that demonstrates the same?

On the other hand if the question is about React itself (eg lifecycle order) then can you please remove the browser API calls from it? Because they would not be relevant.

@gaearon
Copy link
Collaborator

gaearon commented Dec 18, 2017

I took another look. The problem you're having is that forceUpdate() isn't guaranteed to flush synchronously.

When you're inside a React event handler (such as the button click event), React waits for all components to handle the event, and then processes the updates together in a single pass. In most cases this is a good performance optimization because usually it doesn't matter when exactly the update happens.

However, in your case it's actually important that the update is flushed while we're still inside the matchMedia change event handler since otherwise the browser would snapshot the wrong state of the page. You can tell React to force flushing by using this new (currently undocumented) API:

    ReactDOM.flushSync(() => {
      this.forceUpdate();
    });

I have verified that the sandbox using it works as intended: https://codesandbox.io/s/ppykoj2v2q.

I think we'll get around to documenting this API in the future as we further figure out our batching/async changes in React 16, but I hope this is helpful in the meantime!

@gaearon gaearon closed this as completed Dec 18, 2017
@AlexanderLukin
Copy link
Author

Great! Thank you so much, @gaearon!

@yeewai
Copy link

yeewai commented Jun 25, 2019

I'm having this problem still. I'm not sure if this came back in a newer version of react.

The sandbox you posted @gaearon does not work for me. Calling window.print() does not change the word to print but leaves it as screen. Hitting cmd + p does change it to print.

@geongeorge
Copy link

I have made a small hook based on this if anybody is interested

https://github.com/geongeorge/react-use-print

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants