Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get previous url in react gatsby

I am pretty much familiar with the React.js but new to Gatsby.

I want to detect the previous page URL in Gatsby?

like image 853
Profer Avatar asked Mar 01 '19 09:03

Profer


People also ask

How do I get past routes in React hooks?

To detect previous path in React Router, we can set the state property to an object with the location. pathname as the value. <Link to={{ pathname: "/nextpath", state: { prevPath: location.

How do you get the site url in Gatsby?

You can get the current url using the location prop from the @reach/router Location component.

How do I find the url of a reacted page?

Since React is based on regular JavaScript, you can access the location property on the window interface. To get the full path of the current URL, you can use window. location. href , and to get the path without the root domain, access window.


2 Answers

You can pass down state using the Link component:

import React from 'react';
import { Link } from 'gatsby';

const PrevPage = () => (
  <div>
    <Link
      to={`/nextpage`}
      state={{ prevPath: location.pathname }}
    >
      Next Page
    </Link>
  </div>
)

const NextPage = (props) => (
  <div>
    <p>previous path is: {props.location.state.prevPath}</p>
  </div>
);

Then you have access to prevPath from this.props.location.state in the next page.

like image 165
Soroush Chehresa Avatar answered Oct 24 '22 02:10

Soroush Chehresa


Full credit to @soroushchehresa's answer — this answer is just extras built upon it.

Gatsby will throw error during production build, since location is not available during server-side rendering. You could get around it by checking for window object first:

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 }}>
    )
  }
}

But this requires us to implement this on every page, which is tedious. Gatsby has already set up @reach/router for server-side rendering, so we can hook into its location props. Only router components get that props, but we can use @reach/router's Location component to pass it to other components.

With that, we can write a custom Link component that always pass previous url in its state:

// ./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 }

Then we can import our custom Link component instead of Gatsby's Link:

-  import { Link } from 'gatsby'
+  import { Link } from './link-with-prev-url'

Now each Gatsby page component will get this previous url props:

const SomePage = ({ location }) => (
  <div>previous path is {location.state.prevUrl}</div>
);

You might also consider creating a container that store state for the client side & use the wrapRootElement or wrapPageElement in both gatsby-ssr.js and gatsby-browser.js.

like image 12
Derek Nguyen Avatar answered Oct 24 '22 00:10

Derek Nguyen