Data Fetching
What is Data Fetching?
Data fetching is used to make pre-rendering and rendering possible on pages. There are three unique ways Next.js fetches data:
Static Generation -
getStaticProps
Static Generation -
getStaticPaths
Server-side Rendering -
getServerSideProps
Static Generation - getStaticProps
You can export the asynchronous function getStaticProps
from a page and Next.js will pre-render this page at build time using the props that get returned from the function.
Parameters for getStaticProps
getStaticProps
has one parameter, which is an object and can contain the following keys:
params
This key is the route parameter that pages use for dynamic routes.
Let's say a page name is
[id].js
, theparams
will look like{ id: ... }
.This key should be used together with
getStaticPaths
.
preview
This key is
true
if the page is in preview mode.This key is
undefined
in any other case.
previewData
Contains a preview data set by
setPreviewData
locale
Contains the active locale.
This is if you have enabled internationalized routing.
locales
Contains all supported locales.
This is if you have enabled internationalized routing.
defaultLocale
Contains the configured default locale
This is if you have enabled internationalized routing.
Returns for getStaticProps
props
Optional
Object with the props that will be received by the page component
Should be a serialized object.
revalidate
Optional
Amount in seconds after which a page re-generation can occur.
Default is `false`, which means no revalidation.
notFound
Optional
Boolean value to allow the page to return a 404 status and page.
Example:
// inside of getStaticProps function
if (!data) {return {notFound: true,}}
redirect
Optional
Example:
{ destination: string, permanent: boolean}
When should you use getStaticProps
?
If there is data required to render the page that is available at build time ahead of a user's request.
If the data comes from a headless CMS.
If the data can be cached publicly and is not user-specific.
If the page must be pre-rendered and be very fast, like in the case of SEO.
Incremental Static Regeneration
You can create or update static pages after you have built your site. ISR enables you to use static generation per-page. This means you do not have to rebuild your entire site. ISR gives you the benefit of static while you can scale millions of pages.
Using process.cwd()
to read files
Next.js compiles your code into a separate directory, which means you can not use __dirname
since this will not return the correct path.
You can use process.cwd()
instead, since this gives you the directory where Next.js is actually being executed.
Technical Details to keep in mind
getStaticProps
runs on build time only. This means it will not receive data that is only available outside of the build time, like during the request time.Things like query parameters or HTTP headers are not available.
Since
getStaticProps
only runs on the server-side, it can not be run on the client-side.getStaticProps
is not included in the JS bundle for the browser.You can write direct database queries in your code without them getting sent to the browser.
If you do this, make sure you do not fetch an API route from
getStaticProps
, but write it directly in to the code ofgetStaticProps
.
Not only the HTML file gets generated when writing with
getStaticProps
, there is a JSON file that holds the result of runninggetStaticProps
.You can only export
getStaticProps
from a page. The reason is that React needs all required data before the page gets rendered. You will also have to usethe export async function
part, because just addinggetStaticProps
as a property of the page component will not workEvery time you run
next dev
,getStaticProps
will be called.
Static Generation - getStaticPaths
Like said before, if your page has dynamic routes, and it uses getStaticProps, getStaticPaths will need to define a list of paths that have to be rendered to HTML at build time.
The paths
key
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: ...
}
This required key determines which paths actually have to be pre-rendered.
The above code will statically generate
posts/1
andposts/2
at build time.Also, the value of the
params
will have to match the parameters that are used in the page name:Let's say the page name is
pages/posts/[postId]/[commentId]
params
should containpostId
andcommentId
.
If the page name uses a catch-all route like
pages/[...slug]
params
should containslug
.
If you use a catch-all route, supply one of the following:
null
,[]
,undefined
orfalse
to render the root-most route.So if you supply
slug: false` for `pages/[[...slug]]
, Next.js will statically generate the page/
.
The fallback
key
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: ...
}
This key is also required and must contain a boolean value.
fallback: false
This will make sure no paths are returned and will result in a 404 page.
This can be done when a small number of paths has to be pre-rendered, since these get statically generated during build time.
This is also useful if new pages are not added often.
fallback: true
When this is the case, the behavior of
getStaticProps
will change:All paths that get returned from
getStaticPaths
will be rendered to HTML at build time bygetStaticProps
.If there are paths that are not generated, they will not result in a 404 page, Next.js will serve a
fallback
version of the page on the first request to that page.Next.js will statically generate the requested path HTML and JSON in the background, and therefore will also run
getStaticProps.
When the above is finished, the browser receives JSON code for the generated path. This can be used to automatically render the page with the required props. In the eyes of the users, the page will be swapped from a fallback page to a full page.
During all of this, Next.js will add this path to a list of pre-rendered pages.
Is there a moment when
fallback: true
is useful?It is useful when you have a really large number of static pages that all depend on data. You can not pre-render all your product pages, since builds would take absolutely forever.
fallback: blocking
When this is the case, if a new path does not get returned by
getStaticPaths
will wait until HTML is generated, just like in server side rendering. It will then be cached for future requests so this can only happen once per path.
Technical details to keep in mind
Use
getStaticPaths
together withgetStaticProps
, this is a must.getStaticPaths
only runs at build time on server-side.You can only export
getStaticPaths
from a page, not from a component.You must use
export async function
instead of using it as a property of the page component.getStaticPaths
will get called on every request in development.
Server-side Rendering - getServerSideProps
You can export the asynchronous function getServerSideProps
from a page and Next.js will pre-render this page on each request using the data that gets returned by the function.
Parameters for getServerSideProps
getServerSideProps
has one parameter, which is an object that can contain the following keys:
params
This parameter will contain route parameters, if the page uses dynamic routes.
req
HTTP Incoming Message object.
Default is
{}
It will parse an incoming request.
This parameter also provides built in middleware.
The middleware is
req.cookies
.This is an object containing cookies that are sent by request.
res
HTTP response object
query
Object representing the query string.
preview
If set to
true
, the page is in preview mode.false
means otherwise.
previewData
Preview data that is set by
setPreviewData
.
resolvedUrl
Normalized version of the requested URL.
It strips the prefix
_next/data
.
locale
Contains active locale.
If using Internationalized Routing.
locales
Contains all supported locales.
If using Internationalized Routing
defaultLocale
Contains the configured default locale
If using Internationalized Routing
Returns for getServerSideProps
props
Optional
Object with the props that will be received by the page component
Should be either a serializable object or a promise that resolves to a serializable object
notFound
Optional
Boolean value
Allows the page to return a 404 status and page.
redirect
Optional
Redirect value to allow redirecting to internal or external resources.
When should you use getServerSideProps
?
Only if you have to pre-render a page that has data that must be fetched at request time.
Technical details to keep in mind
getServerSideProps
only runs on the server-side. This means a few things:If you request the page directly,
getServerSideProps
runs at request time, the page will be pre-rendered with the returned props.If you request this page on client-side page transitions like
next/link
ornext/router
, an API request gets sent to the server, which will then rungetServerSideProps
. It will return a JSON that contains the result ofgetServerSideProps
.getServerSideProps
is only allowed to be used as a function and in a page
Fetching data on the client side
If you have to frequently update data, you should not pre-render your data. You can instead fetch your data on the client side.
How does client side fetching work?
First it will immediately show the page without data. You can pre-render some parts of the page with static generation, but you can also show loading states for missing data.
After that, you can fetch the data on the client side and it will display when it is ready.
React Hook: SWR
Next.js created a React hook for data fetching which is named SWR. It is recommended to use this when fetching data on the client side, since it will handle the following aspects:
Caching
Revalidation
Focus tracking
Refetching on interval
and more
Example code:
import useSWR from 'swr'
const fetcher = (url) => {
fetch(url).then((res) => {
res.json())
}
}
function Profile() {
const { data, error } = useSWR('/api/user', fetcher)
if (error) {
return <div>failed to load</div>
}
if (!data) {
return <div>loading..</div>
}
return <div>hello {data.name}!</div>}
}
External sources
Next.js documentation about pages
Next.js documentation about data fetching
Images come from Next.js learn