基于 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:

我已尽我所能尝试更新 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>
)