4

I am passing data from one page to another in gatsby. First page code:

let state = {book: book, src: src}
return (
<div className="book__holder">
    <Link to="/pdf/" state={state}>
    <Card
        hoverable
        style={{ width: 240 }}
        cover={<img alt={book} 
                    src={url}
                    />}
        >
        <Meta
            title={book}
            description={faculty+" "+year+"-"+part}
        />
    </Card> 
    </Link> 
</div>

This data is used in pdf page as:

const PDFPage = props =>{
    return (
      <React.Fragment>
       <SEO title={props.location.state.book} />
       <NavBar></NavBar>
       <Embed src={props.location.state.src} type="application/pdf">
       </Embed>

     </React.Fragment>
    )}

export default PDFPage

Everything is fine when using gatsby develop but when i use gatsby build it throws following error:

error Building static HTML for pages failed

See our docs page on debugging HTML builds for help https://gatsby.app    
/debug-html

  11 |   return (
  12 |   <React.Fragment>
> 13 |     <SEO title={props.location.state.book} keywords={[`gatsby`,  
           `application`, `react`]} />
     |                                      ^
  14 |     <NavBar></NavBar>
  15 |     <Embed src={props.location.state.src} type="application/pdf">    
           </Embed>
  16 | 


       WebpackError: TypeError: Cannot read property 'book' of undefined

        - pdf.js:13 PDFPage
         lib/src/pages/pdf.js:13:38

Can anyone help me please?

codedump
  • 347
  • 1
  • 4
  • 13
  • Your `state` is undefined. Please kindly check if you are passing the state down correctly in the routes. – Ru Chern Chong Jan 28 '19 at 13:07
  • As i said above when i am using gastby develop everything is working. PDF loads properly, state is set. But when i run gatsby build error occurs. – codedump Jan 28 '19 at 13:08

2 Answers2

4

Gatsby will throw error during production build, since location is not available during server-side rendering.

One way to make sure the build doesn't throw an error is to:

  1. Check for the window in componentDidMount
  2. Map the location prop to state
  3. Render the value from your state instead of directly from props

In componentDidMount()

componentDidMount() {
  if (typeof window === 'undefined') {
    return;
  }
  this.setState(() => ({ playerName: this.props.location.state.playerName }));
}

In render()

render() {
  return <div>{this.state.playerName}</div>;
}

credit to this thread, How to get previous url in react gatsby

Vien Tang
  • 553
  • 1
  • 5
  • 11
3

Sometimes you’ll want to pass data from the source page to the linked page. You can do this by passing a state prop to the Link component... The linked page will have a location prop containing a nested state object structure containing the passed data.

Passing Props to Link targets

While the following demo is not actually using gatsby, it is using reach router (and gatsby uses reach router under the hood).

import React from "react";
import { render } from "react-dom";
import { Router, Link } from "@reach/router";

const App = () => {
  let state = {
    name: 'Ron',
    book: {
      title: 'Harry Potter and the Deathly Hallows', 
      author: 'J. K. Rowling', 
      progress: '80%'
    }
  }

  return (
  <div>
    <h1>App</h1>
    <nav>
      <Link to="/" state={state}>Home</Link>{" "}
      <Link to="dashboard" state={state} >Dashboard</Link>
    </nav>

    <Router>
      <Home path="/" />
      <Dashboard path="/dashboard" />
    </Router>
  </div>
)};

const Home = ({location}) => (
  <div>
    <h2>Welcome { location.state.name }</h2>
    <p></p>
  </div>
);

const Dashboard = ({location}) => (
  <div>
    <h2>Dashboard</h2>
    <p>Hi { location.state.name }.</p>
    <p>You have read { location.state.book.progress } of { location.state.book.title } by { location.state.book.author }.</p>
  </div>
);

render(<App />, document.getElementById("root"));

Stackblitz

ksav
  • 20,015
  • 6
  • 46
  • 66