-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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] hydrationCompleted is true before hydrated #18670
Comments
These singleton variables are always problematic since they assume a whole lot about app and react implementation details. I don't think these variables are ever correct. What we should do is identify if we actually can use the browser API during render or not. And I think the answer is No for all media queries. An argument can be made to read it during render since it's very unlikely that these value change between render and commit which would produce an inconsistent API. Either way in your particular example useMediaQuery doesn't seem appropriate in the first place. You can use css media queries within the styles declaration. |
@eps1lon What do you think of removing this I think that it will make the logic behave consistently between two renders, the source will be simpler to follow, it would solve this edge case, and hopefully be more resilient to future React changes. |
@toddmazierski We have discussed this concern a bit internally. What do you think of this patch? diff --git a/packages/material-ui/src/useMediaQuery/useMediaQuery.js b/packages/material-ui/src/useMediaQuery/useMediaQuery.js
index e969caa2f..2cb368de0 100644
--- a/packages/material-ui/src/useMediaQuery/useMediaQuery.js
+++ b/packages/material-ui/src/useMediaQuery/useMediaQuery.js
@@ -1,9 +1,6 @@
import React from 'react';
import { getThemeProps, useTheme } from '@material-ui/styles';
-// This variable will be true once the server-side hydration is completed.
-let hydrationCompleted = false;
-
function useMediaQuery(queryInput, options = {}) {
const theme = useTheme();
const props = getThemeProps({
@@ -40,7 +37,7 @@ function useMediaQuery(queryInput, options = {}) {
};
const [match, setMatch] = React.useState(() => {
- if ((hydrationCompleted || noSsr) && supportMatchMedia) {
+ if (noSsr && supportMatchMedia) {
return window.matchMedia(query).matches;
}
if (ssrMatchMedia) {
@@ -54,7 +51,6 @@ function useMediaQuery(queryInput, options = {}) {
React.useEffect(() => {
let active = true;
- hydrationCompleted = true;
if (!supportMatchMedia) {
return undefined;
@@ -80,8 +76,4 @@ function useMediaQuery(queryInput, options = {}) {
return match;
}
-export function testReset() {
- hydrationCompleted = false;
-}
-
export default useMediaQuery; |
Love it. It's less code, and I've confirmed this patch fixes the edge case in our app. Thank you, @oliviertassinari and @eps1lon. 👍 |
@toddmazierski Do you want to submit a pull request? We would still need to update the tests to have it land :). |
Fix a bug where the `hydrationCompleted` variable in `useMediaQuery()` can be set to `true` before all components in the document are actually hydrated. Apply the patch suggested in mui#18670 that removes this optimization in favor of more consistent rendering behavior. Modify the test for this optimization to check for its absence, and elsewhere, remove the use of the `testReset()` test helper function.
You got it! Please see #18683. |
Current Behavior 😯
The
hydrationCompleted
variable inuseMediaQuery()
can becometrue
before all components in the document are actually hydrated.Expected Behavior 🤔
useMediaQuery()
should not have side-effects across components in a single document.Steps to Reproduce 🕹
https://codesandbox.io/s/sweet-wilbur-5t0l6
In this sandbox, please observe that
hydrationCompleted
is set totrue
afterReactDOM.render()
(app 1) but beforeReactDOM.hydrate()
(app 2).Unfortunately, I'm having trouble reproducing the visual bug in our app that caused us to take notice of this issue in the first place. I'll keep at it!
Context 🔦
The impact on our app is
Prop `className` did not match
warnings and mismatches between CSS class names.I'm able to work around the issue by:
hydrationCompleted
back tofalse
after it's set totrue
Your Environment 🌎
The text was updated successfully, but these errors were encountered: