3

I am trying to use react-responsive to conditional rendering components base on device width. Everything worked great in client side, but for SSR I followed the documentation to use Context to pass a specific width for initial server render. However, the width that react-responsive received now hard set to the width in Context even if I resize the browser.

Component to define device base on device width:

import { useMediaQuery } from 'react-responsive';

export const Desktop = ({ children }) => {
const isDesktop = useMediaQuery({ minWidth: 801 });
return isDesktop ? children : null;
};

export const Tablet = ({ children }) => {
const isTablet = useMediaQuery({ minWidth: 426, maxWidth: 800 });
return isTablet ? children : null;
};

export const Mobile = ({ children }) => {
const isMobile = useMediaQuery({ maxWidth: 425 });
return isMobile ? children : null;
};

export const MobileTablet = ({ children }) => {
const isMobile = useMediaQuery({ maxWidth: 800 });
return isMobile ? children : null;
};

My use for DeviceIdentifier component:

...
     <Desktop>
        <CategoryTree />
     </Desktop>

...

      <MobileTablet>
        <BurgerMenu
          open={burgerMenuOpen}
          onOpenStateChange={setBurgerMenuOpen}
        />
      </MobileTablet>
...

Context wrapper in _app.js

import { Context as ResponsiveContext } from 'react-responsive';
...
<ResponsiveContext.Provider value={{ width: 1440 }}>
    <Component {...pageProps} />
</ResponsiveContext.Provider>
...

Since I set the width in the context 1440px, my BurgerMenu component is currently never rendered. Anybody have any idea how to make this react-responsive library work in SRR?

2 Answers 2

1

Could you check for a window object and use that width and hardcode 1440 for server side:

import { Context as ResponsiveContext } from 'react-responsive';
...
<ResponsiveContext.Provider value={{ width: window.innerWidth || 1440 }}>
    <Component {...pageProps} />
</ResponsiveContext.Provider>
...
Sign up to request clarification or add additional context in comments.

Comments

0

From reactjs docs To fix this, either move that logic to useEffect (if it isn’t necessary for the first render), or delay showing that component until after the client renders (if the HTML looks broken until useLayoutEffect runs).

To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with showChild && and defer showing it with useEffect(() => { setShowChild(true); }, []). This way, the UI doesn’t appear broken before hydration.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.