Contents
Hi, in the previous post, i have introduced about NextJs and do a simple tutorial about NextJs. The app we created in previous post is very simple, we are just created a simple app with fixed content from code. You may wondering how to make a dynamic web app with NextJs, how data are controlled and how we can display data from api with NextJs?
Check out these tutorials about Next.js
Next.js + Ant Design with less – Advanced Nextjs and Ant design scaffolding
Convert HTML template into NextJs app
Create custom self-api Next.js api server
NextJs + KoaJs Create custom NextJs server with KoaJs
[Tutorial] Create react based server side rendering app with NextJS
Cloudreports – Next.js tutorials
In this post, i will explain about NextJs data fetching
, we will use the built-in method that shipped with NextJs in it’s core: getInitialProps
NextJs come with a handy method for fetching data both in Server Side and Client Side. As i have wrote in previous post, NextJs support both server side rendering and client side rendering. So data fetching must be implemented in both two sides. With NextJs, we don’t have to implement separate data fetching for server side nor client side.
NextJs build process include two sub processes: Build Server Side code, Build Client Side code. About Data Fetching, we just need to write a part of code, then it will be build into both Server Side and Client Side version.
Let’s try getInitialProps
:
Create NextJs app with data fetching
Assumption that in previous example, we have to display a list of countries that provides from this api: https://cloudreports.net/sample/api/countries.json
Because we are doing data fetching, we need to use an extra library: isomorphic-unfetch
, you can use any other http client library
Install isomorphic-unfetch
import 'isomorphic-unfetch'
npm i isomorphic-unfetch -s
Import isomorphic-unfetch
We will create a static method called getInitialProps
static async getInitialProps() {
}
We use async
here because our http request is asynchronous and it need to be completed before return any data.
Calling http request and wait for it’s response:
static async getInitialProps() {
let res = await fetch('https://cloudreports.net/sample/api/countries.json')
let contriesObj = await res.json()
console.log(contriesObj)
return contriesObj
}
Note:
- You should use try catch in case of broken api link or network error
getInitialProps
must return a javascript object, you can’t return a string or number. If do so, NextJs will throw error in this page.- In this example, we use
isomorphic-unfetch
andjson
method returning a js object parsed from api result console.log
is just for testing api resultgetInitialProps
won’t run until you reload the page contain it. In this case, we need to reload127.0.0.1:3000
The final index.jsx
file will be this:
import React from 'react'
import Link from 'next/link'
import 'isomorphic-unfetch'
export default class HomePage extends React.Component {
static async getInitialProps() {
let res = await fetch('https://cloudreports.net/sample/api/countries.json')
let contriesObj = await res.json()
console.log(contriesObj)
return {countries: contriesObj}
}
render() {
return (
<div>
Hello World.<br />
<Link href='/about'><a>About</a></Link>
</div>
)
}
}
The result:
Now, let me explain a bit about getInitialProps
getInitialProps
is a special method that only existed in NextJs. it only take affect in page level components. When server received a request, NextJs will check corresponding component to see if it have getInitialProps
method. If the current component don’t have this method, NextJs will treat it as a normal component and start rendering.
If a page component contain getInitialProps
method, NextJs will call getInitialProps
first, the result returned from this method will be assign to the component as it’s props. That is why getInitialProps
must return an object, otherwise the merge action will cause error!
Because NextJs will pass getInitialProps
‘s result as component props, we can use it in our render
method
Let’s modify the render
method to display all available countries:
render() {
return (
<div>
Hello World.<br />
<Link href='/about'><a>About</a></Link>
<h2>Country list</h2>
<ul>
{this.props.countries.map((country, i) => {
return (
<li key={'country-' + i}>{country.name}</li>
)
})}
</ul>
</div>
)
}
Move to another page that have getInitialProps
We have index page with getInitialProps
, what happen if our about page have getInitialProps
too? Is getInitialProps
work on xhr request? Let’s check
Modify about page so it will fetch https://cloudreports.net/sample/api/countries.json
and display a list of country codes:
import React from 'react'
import Link from 'next/link'
export default class AboutPage extends React.Component {
static async getInitialProps() {
let res = await fetch('https://cloudreports.net/sample/api/countries.json')
let contriesObj = await res.json()
return {countries: contriesObj}
}
render() {
return (
<div>
About page<br />
<Link href='/'><a>home</a></Link>
<h2>Country codes</h2>
<ul>
{this.props.countries.map((country, i) => {
return (
<li key={'country-' + i}>{country.code}</li>
)
})}
</ul>
</div>
)
}
}
Now navigate to 127.0.0.1:3000
and open developer tool
( network
tab)
click on about
link
as you can see, the loading indicator didn’t animated, browser just send xhr request to fetch countries.json (as api endpoint). Every thing work as expected!
Some notes about using getInitialProps
- We usually use this method to fetch data from external resource (apis), so don’t for get
async
- Always place code inside
try catch
so we can handle unexpected error getInititalProps
must return an object, this object will be passed in to component props- This method will be built into both client and server version, so be careful when expose secure information here
There are some advance and notable tips about using getInitialProps
, i will go deep into these tips in other post. Thank you for reading and please tell me if you have any problems!
Discussion about this post