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] React hydration doesn't re-evaluate the hook #163

Open
Ralle opened this issue Nov 4, 2021 · 3 comments
Open

[useMediaQuery] React hydration doesn't re-evaluate the hook #163

Ralle opened this issue Nov 4, 2021 · 3 comments
Labels
question Further information is requested

Comments

@Ralle
Copy link

Ralle commented Nov 4, 2021

Describe the bug

Next.JS does SSR and this hook sends a false first and then React doesn't update when it client-side detects a true. I made a work-around that makes it work. I am not sure what what internals make this problem occur.

To Reproduce

const isDesktop = useMediaQuery("(min-width:900px)");

I return different HTML depending on whether isDesktop is true or false and it seems like React assumes that that the HTML it got from the server was with isDesktop = true while it was when isDesktop = false. For things like this I have always made a useEffect to change the value and not useState(theCurrentValue) which would cause a discrepancy between server and browser.

Expected behavior
Correctly rendered HTML.

Here is my work-around that makes this work regardless:

  const isDesktop_ = useMediaQuery("(min-width:900px)");

  const [isDesktop, setIsDesktop] = useState(false);

  // Work-around for server-side render
  useEffect(() => {
    setIsDesktop(isDesktop_);
  }, [isDesktop_]);
@jaredLunde
Copy link
Owner

jaredLunde commented Nov 21, 2021

This is always going to be a problem with SSR hydration. I am hesitant to add any logic to the hook to support this, because it encourages the anti-pattern of using JavaScript to change layout instead of CSS in situations where things are clearly being rendered outside of the window while simultaneously making the hook force a new render each client-side render. Probably not the answer you're looking for, but I don't see this changing. Happy to be convinced by others.

@jaredLunde jaredLunde changed the title Next.JS server-side render problem [useMediaQuery] Next.JS server-side render problem Nov 21, 2021
@jaredLunde jaredLunde added the question Further information is requested label Nov 21, 2021
@jaredLunde jaredLunde changed the title [useMediaQuery] Next.JS server-side render problem [useMediaQuery] React hydration doesn't re-evaluate the hook Nov 21, 2021
@Glavin001
Copy link

Glavin001 commented Nov 21, 2021

I had the same issue with useWindowSize.

My workaround:

useSsrCompatible.tsx:

import { useState, useEffect } from "react";

export function useSsrCompatible<T>(newValue: T, initialValue: T) {
    const [value, setValue] = useState(initialValue);
    useEffect(() => {
        setValue(newValue);
    }, [newValue]);
    return value;
}

Then use it like this:

- const [ width, height ] = useWindowSize();
+ const [ width, height ] = useSsrCompatible(useWindowSize(), [0,0]);

which makes Next.js' SSR happy.

Definitely not ideal and makes sense not to include in the library. Although others may find this useful when needing to accomplish this, so glad there is an issue to track the question.

@Ralle
Copy link
Author

Ralle commented Nov 22, 2021

That's very good! I like it a lot.

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

No branches or pull requests

3 participants