on a web application I want to display two different Menu, one for the Mobile, one for the Desktop browser. I use Next.js application with server-side rendering and the library react-device-detect.
Here is the CodeSandox link.
import Link from "next/link";
import { BrowserView, MobileView } from "react-device-detect";
export default () => (
<div>
Hello World.{" "}
<Link href="/about">
<a>About</a>
</Link>
<BrowserView>
<h1> This is rendered only in browser </h1>
</BrowserView>
<MobileView>
<h1> This is rendered only on mobile </h1>
</MobileView>
</div>
);
If you open this in a browser and switch to mobile view and look the console you get this error:
Warning: Text content did not match. Server: " This is rendered only in browser " Client: " This is rendered only on mobile "
This happen because the rendering by the server detects a browser and on the client, he is a mobile device. The only workaround I found is to generate both and use the CSS like this:
.activeOnMobile {
@media screen and (min-width: 800px) {
display: none;
}
}
.activeOnDesktop {
@media screen and (max-width: 800px) {
display: none;
}
}
Instead of the library but I don't really like this method. Does someone know the good practice to handle devices type on an SSR app directly in the react code?
LATEST UPDATE:
So if you don't mind doing it client side you can use the dynamic importing as suggested by a few people below. This will be for use cases where you use static page generation.
i created a component which passes all the
react-device-detectexports as props (it would be wise to filter out only the needed exports because then does not treeshake)and then when you want to make use of the component you can just do
Personally I just use a hook to do this, although the initial props method is better.
I had the problem that scroll animation was annoying on mobile devices so I made a device based enabled scroll animation component;
UPDATE:
so after further going down the rabbit hole, the best solution i came up with is using the react-device-detect in a useEffect, if you further inspect the device detect you will notice that it exports const's that are set via the
ua-parser-jslibThis results in the initial device being the server which causes false detection.
I forked the repo and created and added a ssr-selector which requires you to pass in a user-agent. which could be done using the initial props
UPDATE:
Because of Ipads not giving a correct or rather well enough defined user-agent, see this issue, I decided to create a hook to better detect the device
Because I require the package each time I call that hook, the UA info is updated, it also fixes to SSR out of sync warnings.