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 getStaticPropsexport 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:
`getStaticPaths`
: to tell Next.js all the routes that we want to be rendered.`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.