Рендеринг страницы на сервере Gatsby с использованием только клиентских маршрутов в зависимости от расположения окна - PullRequest
0 голосов
/ 19 января 2020

Я работаю над проектом Gatsby (блог по изучению языка) и испытываю проблемы с проблемой, которая возникает только в производственных сборках из-за рендеринга на стороне сервера.

Я программно генерирую страницу для каждого блога пост по следующей схеме: /posts/{post-name}. Каждое сообщение также может иметь несколько подпутей, которые сопоставляются с открытыми вкладками в пользовательском интерфейсе. Например, /posts/important-spanish-verbs/lesson откроет вкладку урока. Каждая страница имеет свойство matchPath, равное /posts/{post-name}/*, и оно обрабатывается как клиентские маршруты, реализованные с помощью reach-router.

При gatsby develop приложение работает точно так, как задумано. Когда я захожу на /posts/some-post/podcast, он успешно открывается на вкладке подкаста, и я вижу, что активная вкладка установлена ​​правильно.

Проблема в том, что с gatsby build && gatsby serve, когда я освобождаю sh - загружаю URL при прямой ссылке на указанную c вкладку внутри сообщения (либо вручную, либо просматривая весь URL-адрес, либо обновляя), активная вкладка не установлена ​​правильно в пользовательском интерфейсе.

Следующее фрагмент (очень упрощенный и сжатый, чтобы продемонстрировать проблему) в общих чертах описывает проблему:

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 (т. Е. content вкладки урока
  • вкладка урока имеет класс inactive (ошибка)
  • В консоли я вижу напечатанный tab /posts/example-post/lesson active? true, хотя класс CSS не обновлялся !

Я попробовал все, что я Можно подумать, чтобы попытаться обновить пользовательский интерфейс. Как только я щелкаю по другой вкладке и местоположение окна изменяется без ссылки sh, все обновляется нормально, и активный интерфейс активной вкладки работает, как и ожидалось, но я просто не могу заставить его перерисовать на основе переменной isActive.

Кто-нибудь знает способ исправить или обойти эту проблему?

Спасибо!

1 Ответ

1 голос
/ 20 января 2020

Мне удалось найти обходной путь для этой проблемы, хотя это немного расстраивает, когда я не понимаю в деталях, почему проблема действительно возникает.

Если я обертываю вкладку <li> s (которая не t правильно показывать как активный / неактивный при первой загрузке с SSR) в условии, чтобы проверить, что мы в браузере, это работает:

return typeof window !== 'undefined' && (
  <li className={isActive ? 'active' : 'inactive'}>
    {/* construct a link based on child props */}
  </li>
)
...