Data Fetching

How to fetch JSON:API data from Drupal.


In Next.js, you fetch server-side data in either `getStaticProps` or `getServerSideProps`. Data is then fed to your pages for pre-rendering.

next-drupal provides several functions to help you query JSON:API data from Drupal.

Basic Example

Here's an example which uses `getResource` to fetch a `page` node by ID:

export async function getStaticProps() {
const node = await getResource(
"node--page",
"07464e9f-9221-4a4f-b7f2-01389408e6c8"
)
}

A full page would look like this:

pages/about.tsx

// node will be populated at build time by getStaticProps
export default function AboutPage({ node }) {
return (
<article>
<h1>{node.title}</h1>
// ...
</article>
)
}
export async function getStaticProps() {
// Fetch the node from Drupal.
const node = await getResource(
"node--page",
"07464e9f-9221-4a4f-b7f2-01389408e6c8"
)
// Pass the node as props to the AboutPage.
return {
props: {
node,
},
}
}

Dynamic pages

You can use Next.js dynamic route to build static pages for every node (or any entity type).

Start by creating a page at `/pages/[...slug].tsx`, where `[...slug]` maps to the path alias for a node in Drupal.

This means `/pages/[...slug].tsx` will handle all pages with the following aliases: `/about`, `/team`, `/another/path` ...etc.

To build static pages for these nodes, there are two functions we need to implement:

  1. `getStaticPaths`: to tell Next.js all the routes that we want to be rendered.
  2. `getStaticProps`: to fetch data for pages.

pages/[...slug].tsx

import { getPathsFromContext, getResourceFromContext } from "next-drupal"
export default function Page({ node }) {
return (
<article>
<h1>{node.title}</h1>
// ...
</article>
)
}
export async function getStaticPaths(context) {
// Build paths for all `node--page`.
return {
paths: await getPathsFromContext("node--page", context),
fallback: false,
}
}
export async function getStaticProps(context) {
// Fetch the node based on the context.
// next-drupal automatically handles the slug value.
const node = await getResourceFromContext("node--page", context)
return {
props: {
node,
},
}
}

Advanced Example

In the example above, we used `pages/[...slug].tsx` to build static pages for `node--page`.

We can go a step further and handle all node types (or any entity type) in one page.

To do that, we're going to use `getResourceTypeFromContext` which returns the resource type based on `context`.

export async function getStaticProps(context) {
const type = await getResourceTypeFromContext(context)
if (type === "node--article") {
// Build custom JSON:API query for article.
}
if (type === "node--page") {
// Build custom JSON:API query for page.
}
}

Let's update `pages/[...slug].tsx` to handle both `node--page` and `node--article`.

pages/[...slug].tsx

import {
getPathsFromContext,
getResourceFromContext,
getResourceTypeFromContext,
} from "next-drupal"
import { DrupalJsonApiParams } from "drupal-jsonapi-params"
export default function Page({ node }) {
if (node.type === "node--page") {
return <PageComponent />
}
if (node.type === "node--article") {
return <ArticleComponent />
}
return null
}
export async function getStaticPaths(context) {
// Build paths for all `node--page` and `node--article`.
return {
paths: await getPathsFromContext(["node--page", "node--article"], context),
fallback: false,
}
}
export async function getStaticProps(context) {
const params = new DrupalJsonApiParams()
const type = await getResourceTypeFromContext(context)
// Fetch the title, path and body field for pages.
if (type === "node--page") {
params.addFields("node--page", ["title", "path", "body"])
}
// Fetch additional fields for articles.
if (type === "node--article") {
params.addFields("node--article", ["title", "path", "body", "uid"])
}
const node = await getResourceFromContext(type, context, {
params: params.getQueryObject(),
})
return {
props: {
node,
},
}
}

Reference

See the reference section for more examples of fetching resources and collection of resources.