While using the MUI useMediaQuery hook, I noticed my react app being buggy and throwing errors because the hook initially does not recognise the correct breakpoint, then the page quickly re-renders with the correct value.
Example:
const mobile = useMediaQuery((theme) => theme.breakpoints.only('mobile'));
console.log(mobile)
Console:
false
true
What's going on?
This is the expected behaviour of useMediaQuery hook. It's explained in the MUI docs:
To perform the server-side hydration, the hook needs to render twice. A first time with false, the value of the server, and a second time with the resolved value. This double pass rendering cycle comes with a drawback. It's slower. You can set this option to true if you are doing client-side only rendering.
So to get the correct value on the first page render the noSsr option in the useMediaQuery hook needs to be true.
There are two options:
1) Per component:
const mobile = useMediaQuery((theme) => theme.breakpoints.only('mobile'), {noSsr: true});
2) Globally in the theme object:
const theme = createTheme({
components: {
MuiUseMediaQuery: {
defaultProps: {
noSsr: true,
},
},
}
Obviously, this will only work without server-side rendering.
The original answer below works in Material-UI v4, but the Hidden component has been deprecated in v5.
Original answer:
I realised that by removing the media query and replacing it with the Material-UI <Hidden /> component it works how I want it to.
export const ResponsiveMenuItem = forwardRef((props, ref) => {
const { children, ...other } = props;
return (
<>
<Hidden smUp>
<option ref={ref} {...other}>
{children}
</option>
</Hidden>
<Hidden only="xs">
<MenuItem ref={ref} {...other}>
{children}
</MenuItem>
</Hidden>
</>
);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With