基于 window 位置的 Gatsby 服务器端页面呈现,仅包含客户端路由
Gatsby server-side rendering of page with client-only routes, based on window location
我正在处理一个 Gatsby 项目(一个语言学习博客),我遇到了一个问题,这个问题只发生在生产构建中,因为服务器端呈现。
我使用以下方案以编程方式为每个博客 post 生成一个页面:
/posts/{post-name}
。每个 post 还可以有许多子路径映射到 UI 中打开的选项卡。例如,/posts/important-spanish-verbs/lesson
将打开课程选项卡。每个页面都有一个 matchPath
属性 的 /posts/{post-name}/*
,这些被处理为仅客户端路由,用 reach-router
.
实现
使用 gatsby develop
,该应用程序完全按预期运行。当我访问 /posts/some-post/podcast
时,它成功打开了播客选项卡,我可以看到活动选项卡设置正确。
问题是 gatsby build && gatsby serve
,当我重新加载 URL 时直接导航到 post 内的特定选项卡(手动访问整个 URL 或刷新),活动选项卡 未 在 UI.
中正确设置
以下代码片段(经过高度简化和浓缩以演示问题)大致概述了问题:
function TabbedLayout({ children, basePath }) {
return (
<LocationProvider>
{({ location }) => {
return (
<Fragment>
<ul>
React.Children.map(children, (child, index) => {
const isActive = child.props.path === location.pathname
console.log(`tab ${child.props.path} active? ${isActive}`)
return <li className={isActive ? 'active' : 'inactive'}>{/* construct a link based on child props */}</li>
})
</ul>
<Router basepath={basePath}>
{children}
</Router>
</Fragment>
)
}}
</LocationProvider>
}
当我 运行 我的代码在 生产构建 (使用 SSR)中使用上面演示的方法时会发生什么,例如当我访问 posts/example-post/lesson
:
- 内容 通过 Reach 路由器正确呈现(即课程选项卡的 内容 已打开)
- 课程选项卡有class
inactive
(错误)
- 在控制台中,我看到打印了
tab /posts/example-post/lesson active? true
,即使 CSS class 没有更新!
我已尽我所能尝试更新 UI。一旦我单击不同的选项卡并且 window 位置更改 而没有刷新 ,一切都会更新并且活动选项卡 UI 按预期工作,但我只是似乎无法根据 isActive
变量重新渲染它。
有谁知道解决或解决此问题的方法吗?
谢谢!
我已经设法找到了该问题的解决方法,尽管无法详细了解问题实际发生的原因有点令人沮丧。
如果我将选项卡 <li>
s(在第一次使用 SSR 加载时未正确显示为 active/inactive)包装在一个条件中以检查我们是否在浏览器中,它可以工作:
return typeof window !== 'undefined' && (
<li className={isActive ? 'active' : 'inactive'}>
{/* construct a link based on child props */}
</li>
)
我正在处理一个 Gatsby 项目(一个语言学习博客),我遇到了一个问题,这个问题只发生在生产构建中,因为服务器端呈现。
我使用以下方案以编程方式为每个博客 post 生成一个页面:
/posts/{post-name}
。每个 post 还可以有许多子路径映射到 UI 中打开的选项卡。例如,/posts/important-spanish-verbs/lesson
将打开课程选项卡。每个页面都有一个 matchPath
属性 的 /posts/{post-name}/*
,这些被处理为仅客户端路由,用 reach-router
.
使用 gatsby develop
,该应用程序完全按预期运行。当我访问 /posts/some-post/podcast
时,它成功打开了播客选项卡,我可以看到活动选项卡设置正确。
问题是 gatsby build && gatsby serve
,当我重新加载 URL 时直接导航到 post 内的特定选项卡(手动访问整个 URL 或刷新),活动选项卡 未 在 UI.
以下代码片段(经过高度简化和浓缩以演示问题)大致概述了问题:
function TabbedLayout({ children, basePath }) {
return (
<LocationProvider>
{({ location }) => {
return (
<Fragment>
<ul>
React.Children.map(children, (child, index) => {
const isActive = child.props.path === location.pathname
console.log(`tab ${child.props.path} active? ${isActive}`)
return <li className={isActive ? 'active' : 'inactive'}>{/* construct a link based on child props */}</li>
})
</ul>
<Router basepath={basePath}>
{children}
</Router>
</Fragment>
)
}}
</LocationProvider>
}
当我 运行 我的代码在 生产构建 (使用 SSR)中使用上面演示的方法时会发生什么,例如当我访问 posts/example-post/lesson
:
- 内容 通过 Reach 路由器正确呈现(即课程选项卡的 内容 已打开)
- 课程选项卡有class
inactive
(错误) - 在控制台中,我看到打印了
tab /posts/example-post/lesson active? true
,即使 CSS class 没有更新!
我已尽我所能尝试更新 UI。一旦我单击不同的选项卡并且 window 位置更改 而没有刷新 ,一切都会更新并且活动选项卡 UI 按预期工作,但我只是似乎无法根据 isActive
变量重新渲染它。
有谁知道解决或解决此问题的方法吗?
谢谢!
我已经设法找到了该问题的解决方法,尽管无法详细了解问题实际发生的原因有点令人沮丧。
如果我将选项卡 <li>
s(在第一次使用 SSR 加载时未正确显示为 active/inactive)包装在一个条件中以检查我们是否在浏览器中,它可以工作:
return typeof window !== 'undefined' && (
<li className={isActive ? 'active' : 'inactive'}>
{/* construct a link based on child props */}
</li>
)