ton*_*on1 6 reactjs server-side-rendering next.js
我有<MobileLayout />,<DesktopLayout />。我用于Next.js服务器端渲染。我注意到有许多著名的 ui 库都有移动检测组件,例如<Respnosive />Semantic-UI-React 中的组件。但所有这些都是客户端方法,无法正常工作SSR
我阅读了一些文档,结论是我应该检查user-agent服务器端req.headers。在 Next.js 中,检测设备并有条件渲染MobileLayout/之一的正确方法是什么DesktopLayout?
我尝试过的
在_app.js
import isMobile from 'ismobilejs'
...
function Homepage({ Component, pageProps, mobile }){
return (
mobile ?
<MobileLayout><Component {...pageProps} /></MobileLayout> :
<DesktopLayout><Component {...pageProps} /></DesktopLayout>
)
}
HomePage.getInitialProps = async (appContext) => {
const userAgent = appContext.ctx.req.headers['user-agent']
const mobile = isMobile(userAgent).any
const appProps = await App.getInitialProps(appContext)
return { ...appProps, mobile }
}
Run Code Online (Sandbox Code Playgroud)
但问题是 getIntialProps 在_app.js每次页面加载时执行。通过与客户端移动页面,它appContext.ctx会undefined省略错误。我认为这个方法可能会阻止一些 nextjs 内置优化。
错误页面中的错误
getInitialProps:TypeError:无法读取未定义的属性“标题”
那么在 Next.js 中检查设备的正确方法是什么?
如果您想使用 检测用户的设备userAgent,最好的选择是这个答案:
IndexPage.getInitialProps = ({ req }) => {
let userAgent;
if (req) { // if you are on the server and you get a 'req' property from your context
userAgent = req.headers['user-agent'] // get the user-agent from the headers
} else {
userAgent = navigator.userAgent // if you are on the client you can access the navigator from the window object
}
}
Run Code Online (Sandbox Code Playgroud)
(请注意,如果您有 Next 9.3 或更高版本,您实际上应该使用 getServerSidePropsor getStaticProps,但有时该功能没有替代品getInitialProps。)
然而,Mozilla 的人员建议:
值得重申的是:使用用户代理嗅探很少是个好主意。您几乎总能找到更好、更广泛兼容的方法来解决您的问题!
您正在导入的isMobile 包的制造商甚至警告:
您可能不需要这个库。在大多数情况下,响应式设计 解决了控制如何在不同屏幕尺寸上渲染事物的问题。
因此,看看是否可以使用CSS3 媒体查询来有条件地渲染某些元素或更改其大小等,而不是使用完全独立的移动和桌面布局组件。但您可能会遇到一种极端情况,无法使任何替代选项发挥作用。
如果您要保留当前设置并在其他页面上使用两种布局,您可以考虑将它们组合到一个父<Layout>组件中,该父组件有条件地呈现其中一个或另一个,这样您就不必将该逻辑复制到每个页面中:
export const Layout = (props) => {
return (
props.mobile ?
<MobileLayout>{props.children}</MobileLayout> :
<DesktopLayout>{props.children}</DesktopLayout>
)
}
Run Code Online (Sandbox Code Playgroud)