Полный кредит на @ ответ soroushchehresa - этот ответ является просто дополнением, построенным на нем.
Гэтсби выдаст ошибку во время производственной сборки, так как location
недоступен на стороне серверарендеринг.Вы можете обойти это, проверив сначала объект window
:
class Page extends React.Component {
state = {
currentUrl: '',
}
componentDidMount() {
if (typeof window == 'undefined') return
this.setState({ currentUrl: window.location.href })
}
render() {
return (
<Link to="..." state={{ prevUrl: this.state.currentUrl }}>
)
}
}
Но это требует от нас реализации этого на каждой странице, что утомительно.Gatsby уже настроил @reach/router
для рендеринга на стороне сервера, поэтому мы можем подключиться к его location
реквизиту.Только компоненты маршрутизатора получают этот реквизит, но мы можем использовать компонент @reach/router
Location
для передачи его другим компонентам.
С этим мы можем написать собственный компонент Link, которыйвсегда передавайте предыдущий URL в его состоянии:
// ./src/components/link-with-prev-url.js
import React from 'react'
import { Location } from '@reach/router'
import { Link } from 'gatsby'
const LinkWithPrevUrl = ({ children, state, ...rest }) => (
<Location>
{({ location }) => (
//make sure user's state is not overwritten
<Link {...rest} state={{ prevUrl: location.href, ...state}}>
{ children }
</Link>
)}
</Location>
)
export { LinkWithPrevUrl as Link }
Тогда мы можем импортировать наш пользовательский компонент Link вместо ссылки Gatsby:
- import { Link } from 'gatsby'
+ import { Link } from './link-with-prev-url'
Теперь каждый компонент страницы Gatsby получит этот предыдущий URL-реквизит:
const SomePage = ({ location }) => (
<div>previous path is {location.state.prevUrl}</div>
);
Вы можете также рассмотреть возможность создания контейнера, в котором хранится состояние для клиентской стороны, и использовать wrapRootElement
или wrapPageElement
ingatsby-ssr.js
и gatsby-browser.js
.