---
title: Code components - Data fetching
---

import { Aside } from '@astrojs/starlight/components';

## SWR

[SWR](https://swr.vercel.app/) is provided as a native package and can be
imported and used for general data fetching. Data returned will be shown in the
"Data Fetch" pane under the component preview.

```jsx
import useSWR from 'swr';

export default function Profile() {
  const { data, error, isLoading } = useSWR(
    'https://my-site.com/api/user',
    fetcher,
  );

  if (error) return <div>failed to load</div>;
  if (isLoading) return <div>loading...</div>;
  return <div>hello {data.name}!</div>;
}
```

![Drupal's Drupal Canvas data fetch pane showing the results of fetching
menus data as JSON](../../../assets/images/data-fetch-1.webp)

## Drupal data

### Page and site data

You can access information about the current page with the `getPageData`
utility. Results can be viewed in the Data Fetch pane below the component
preview.

```js
import { getPageData } from 'drupal-canvas';

const { pageTitle, breadcrumbs } = getPageData();
```

You can also access site information with the `getSiteData` utility

```js
import { getSiteData } from 'drupal-canvas';

const { siteName } = getSiteData().branding;
```

![Drupal's Drupal Canvas data fetch pane showing the results of access page
and site data](../../../assets/images/data-fetch-2.webp)

### JSON:API

[drupal-canvas](https://www.npmjs.com/package/drupal-canvas) provides the
[JSON:API client](https://www.npmjs.com/package/@drupal-api-client/json-api-client)
automatically configured with a `baseUrl` as well as
[Jsona](https://www.npmjs.com/package/jsona) for
[deserialization](https://project.pages.drupalcode.org/api_client/jsonapi-tutorial/deserializing-data/).
[Drupal core's JSON:API module](https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module)
must be enabled to use this client.

The associated
[parameter helper package](https://project.pages.drupalcode.org/api_client/jsonapi-tutorial/parameters/#generating-query-strings-with-drupal-jsonapi-params)
is also included as a native package.

```jsx
import { JsonApiClient } from 'drupal-canvas';
import { DrupalJsonApiParams } from 'drupal-jsonapi-params';
import useSWR from 'swr';

const client = new JsonApiClient();

export default function List() {
  const { data, error, isLoading } = useSWR(
    [
      'node--article',
      {
        queryString: new DrupalJsonApiParams()
          .addInclude(['field_tags'])
          .getQueryString(),
      },
    ],
    ([type, options]) => client.getCollection(type, options),
  );

  if (error) return 'An error has occurred.';
  if (isLoading) return 'Loading...';
  return (
    <ul>
      {data.map((article) => (
        <li key={article.id}>{article.title}</li>
      ))}
    </ul>
  );
}
```

You can override the `baseUrl` and any default options:

```js
const client = new JsonApiClient('https://drupal-api-demo.party', {
  serializer: undefined,
  cache: undefined,
});
```

<Aside type="tip">
  For development outside of Drupal Canvas, use
  [`@drupal-canvas/vite-plugin`](https://www.npmjs.com/package/@drupal-canvas/vite-plugin)
  to automatically provide the necessary configuration based on environment
  variables.
</Aside>

<Aside>
  When working with Code Components outside of Drupal Canvas, you may need to
  configure CORS headers on your Drupal site to allow JSON:API requests from
  your development environment.
</Aside>

### Helper utilities

Utility functions for working with JSON:API and core APIs are provided in the
[`drupal-canvas`](https://www.npmjs.com/package/drupal-canvas) package.

### Examples

#### Fetching nodes with JSON:API

The following example fetches nodes using a preconfigured version of the
[JSON:API client from the Drupal API Client](https://project.pages.drupalcode.org/api_client),
and outputs links to each of them using the `getNodePath` utility from the
`drupal-canvas` package, which will return the path alias if exists, or fall
back to the `/node/[nid]` path.

```jsx
import { getNodePath, JsonApiClient } from 'drupal-canvas';
import { DrupalJsonApiParams } from 'drupal-jsonapi-params';
import useSWR from 'swr';

const Articles = () => {
  const client = new JsonApiClient();
  const { data, error, isLoading } = useSWR(
    [
      'node--article',
      {
        queryString: new DrupalJsonApiParams()
          .addSort('created', 'DESC')
          .getQueryString(),
      },
    ],
    ([type, options]) => client.getCollection(type, options),
  );

  if (error) return 'An error has occurred.';
  if (isLoading) return 'Loading...';
  return (
    <ul>
      {data.map((article) => (
        <li key={article.id}>
          <a href={getNodePath(article)}>{article.title}</a>
        </li>
      ))}
    </ul>
  );
};

export default Articles;
```

#### Using the JSON:API Menu Items module

This example builds a navigation menu using the
[JSON:API Menu Items module](https://www.drupal.org/project/jsonapi_menu_items):

```jsx
import { JsonApiClient, sortMenu } from 'drupal-canvas';
import useSWR from 'swr';

const client = new JsonApiClient();

const Navigation = () => {
  const { data, isLoading, error } = useSWR(
    ['menu_items', 'main'],
    ([type, resourceId]) => client.getResource(type, resourceId),
  );
  if (error) return 'An error has occurred.';
  if (isLoading) return 'Loading...';

  const menu = sortMenu(data);

  return (
    <ul>
      {menu.map((item) => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
};

export default Navigation;
```

#### Using Drupal core's linkset endpoint

You can also build a navigation menu using
[Drupal core's linkset endpoint](https://www.drupal.org/docs/develop/decoupled-drupal/decoupled-menus/decoupled-menus-overview).

```jsx
import { sortLinksetMenu } from 'drupal-canvas';
import useSWR from 'swr';

const Navigation = () => {
  const { data, isLoading, error } = useSWR(
    '/system/menu/main/linkset',
    async (url) => {
      const response = await fetch(url);
      return response.json();
    },
  );
  if (error) return 'An error has occurred.';
  if (isLoading) return 'Loading...';

  const menu = sortLinksetMenu(data);

  return (
    <ul>
      {menu.map((item) => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
};

export default Navigation;
```
