在一个网络应用程序上,我想显示两个不同的菜单,一个用于移动设备,一个用于桌面浏览器。我将 Next.js 应用程序与服务器端渲染和库 react-device-detect 一起使用。
这是 CodeSandox 链接。
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>
);
如果您在浏览器中打开它并 切换到移动 视图并查看控制台,您会收到此错误:
警告:文本内容不匹配。服务器:“仅在浏览器中呈现”客户端:“仅在移动设备上呈现”
发生这种情况是因为服务器的渲染检测到浏览器,而在客户端,他是移动设备。我发现的唯一解决方法是同时生成并使用 CSS,如下所示:
.activeOnMobile {
@media screen and (min-width: 800px) {
display: none;
}
}
.activeOnDesktop {
@media screen and (max-width: 800px) {
display: none;
}
}
而不是图书馆,但我真的不喜欢这种方法。有人知道直接在反应代码中处理 SSR 应用程序上的设备类型的良好做法吗?
原文由 Benjamin Sx 发布,翻译遵循 CC BY-SA 4.0 许可协议
最近更新:
因此,如果您不介意在客户端执行此操作,则可以使用下面一些人建议的动态导入。这将适用于您使用静态页面生成的用例。
我创建了一个组件,它通过所有
react-device-detect
导出作为道具(明智的做法是只过滤掉所需的导出,因为这样不会摇晃)然后当您想使用该组件时,您可以这样做
就我个人而言,我只是使用一个钩子来做到这一点,虽然最初的 props 方法更好。
我遇到了滚动动画在移动设备上很烦人的问题,所以我制作了一个基于设备的启用滚动动画组件;
更新:
因此,在进一步深入兔子洞之后,我想出的最佳解决方案是在 useEffect 中使用 react-device-detect,如果您进一步检查设备检测,您会注意到它导出通过
ua-parser-js
设置的 const---
库这导致初始设备是导致错误检测的服务器。
我分叉了 repo 并创建并添加了一个 ssr-selector ,它要求你传入一个用户代理。这可以使用初始道具来完成
更新:
由于 Ipads 没有提供正确或定义得足够好的用户代理,请参阅这个 问题,我决定创建一个挂钩来更好地检测设备
因为我每次调用该钩子时都需要该包,所以更新了 UA 信息,它还修复了 SSR 不同步警告。