Gatsby: Server side rendering from ajax/fetch/axios GET data

Created on 24 Jan 2018  路  6Comments  路  Source: gatsbyjs/gatsby

I have asked on SO but without any response:
https://stackoverflow.com/questions/48419175/gatsby-server-side-rendering-ajax-xhr-axios

Is it possible with gatsby to render some external data server side to have prepopulated content when accessing page with browser?

Lets assume i have a public api endpoint like this: http://jsonplaceholder.typicode.com/posts
I want data from such endpoint rendered also server side.

Current behaviour:

Currently when doing axios get calls in my component(constructor or componentDidMount) im able to see data downloaded and rendered fully client side

Expected result

I want to be able to call external data in react component (maybe marking with async/await) to have it rendered server-side after ajax call wil be finished.

I found something regarding graphQL(iam not familiar with it) that it is able to query data also for server side rendering.

But how to achieve my needs using simple text/json response from external endpoint?

question or discussion

All 6 comments

If a plugin exists to pull data from your source of choice, then you can pull it in and use GraphQL to query it.

https://www.gatsbyjs.org/docs/plugins/

If it doesn't, you'll want to write a plugin to pull data or use the sourceNodes API in your gatsby-node.js file.

https://www.gatsbyjs.org/docs/node-apis/#sourceNodes

Closing this and responding with this answer on SO.

// on your gatsby-node.js file
exports.onCreatePage = async ({ page }) => {
    if (true) { // check here if the page is the page you want add data, using some page property to check
        page.context.foo = await axios.get("https://swapi.co/api/people/1/")
    }
}

// On page, use console.log(props) to see the added data

Hey @lukaszblasz just checking in to know your experience of using the suggested solution. I am also having a somewhat similar problem. Basically would like to consume the RESTFul APIs of our server which is serving the existing production mobile apps.

@hhsadiq Yes above solution works perfectly. Thank you @netojose
My gatsby-node.js file

const axios = require('axios'); 

exports.onCreatePage = async ({ page }) => {
        const response = await axios.get("http://jsonplaceholder.typicode.com/posts");
        page.context.test = response.data;
}

Than in every page, our test variable is available under props.pageContext.test

For my example data will be availabe for every page under /pages. You will need to have some conditional statements to have it only for pages you want. Of course you can then pass that from pages to 'dumb' displaying components.

@lukaszblasz I've copied your code verbatim and still get a props undefined in my index.js under my pages folder. Any idea?
Cannot read property 'context' of undefined
message: "internalInstance is null"

@thebetterjort i have double checked and everything works fine. Above code need to be placed in gatsby-node.js and then your page file may looks like:

import React, { Component } from 'react';
class IndexPage extends Component {

    constructor(props) {
        super(props);
        console.log(props.pageContext);
    }

    render() {
        return <div className='page-home'></div>
    }
}

export default IndexPage;
Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  路  3Comments

kalinchernev picture kalinchernev  路  3Comments

benstr picture benstr  路  3Comments

totsteps picture totsteps  路  3Comments

brandonmp picture brandonmp  路  3Comments