1. Component-level data fetching in Next.js apps

Use GraphQL to fetch component-level data in a Next.js Content SDK app

Version:

The following example describes how to execute server-side GraphQL queries to get data and use it to populate components. Although this example does not use code generation to automatically create the required types of GraphQL queries and return objects, we strongly recommend introducing code generation in your own work flow.

Before you begin

To use GraphQL to fetch component-level data in a Next.js app:

  1. In your component file, define a GraphQL query. For example:

    const myGraphQLQuery = `
    query ($datasource: String!, $contextItem: String!, $language: String!) {
      # Datasource query
      # $datasource should be set to the ID of the rendering's datasource item
      datasource: item(path: $datasource, language: $language) {
        id
        name
      }
      
      # Context/route item query
      # $contextItem should be set to the ID of the current context item (the route item)
      contextItem: item(path: $contextItem, language: $language) {
        id
        # Get the page title from the Page template
        ...on Page {
          pageTitle {
            value
          }
        }
        # List the children of the current route
        children(hasLayout: true) {
          results {
            id
            # typing fragments can be used anywhere!
            # so in this case, we're grabbing the 'pageTitle'
            # field on all child route items.
            ...on Page {
              pageTitle {
                value
              }
            }
            url {
              path
            }
          }
        }
      }
    }`
  2. Also in your component file, add the following import statements:

    import React, { JSX } from 'react';
    import { Field, RichText as JssRichText } from '@sitecore-content-sdk/nextjs';
    import { ComponentProps } from 'lib/component-props';
    import { GraphQLRequestClient } from '@sitecore-content-sdk/nextjs/client';
    import scConfig from 'sitecore.config';
  3. Define the types for the result of the GraphQL query. For example:

    type Item = {
      id: string;
      url: {
        path: string;
      };
      pageTitle: {
        value: string;
        jsonValue: {
          value: string;
        };
      };
    };
    
    type ItemSearchResults = {
      results: Item[];
    };
    
    type GraphQLDemoDataSource = {
      name: string;
      id: string;
    };
  4. Define your TypeScript types and the GraphQLDemo component:

    type GraphQLDemoData = {
      datasource: {
        name: string;
        id: string;
      };
      contextItem: {
        id: string;
        children: ItemSearchResults;
        pageTitle: {
          value: string;
        };
      };
    };
    
    type GraphQLDemoProps = ComponentProps & GraphQLDemoData;
    const GraphQLDemo = (props: GraphQLDemoProps): JSX.Element => {
      return (
        // your markup
      );
    };
  5. Define the getComponentServerProps function and initialize GraphQLRequestClient:

    import { GraphQLRequestClient } from '@sitecore-content-sdk/nextjs/client';
    ...
    export const getComponentServerProps = async (rendering, layoutData) => {
      const graphqlendpoint = `https://${scConfig.api.local.apiHost}/sitecore/api/graph/edge`;
      const graphQLClient = new GraphQLRequestClient(graphqlendpoint, {
        scConfig.api.local.apiKey,
      });
    }
  6. Perform the request and return the result:

    import { GraphQLRequestClient } from '@sitecore-content-sdk/nextjs/client';
    ...
    export const getComponentServerProps = async (rendering, layoutData) => {
      const graphqlendpoint = `https://${scConfig.api.local.apiHost}/sitecore/api/graph/edge`;
      const graphQLClient = new GraphQLRequestClient(graphqlendpoint, {
        scConfig.api.local.apiKey,
      });
      
      const result = await graphQLClient.request<YourResultType>(
        myGraphQLQuery, 
        {
          datasource: rendering.dataSource,
          contextItem: layoutData?.sitecore?.route?.itemId,
          language: layoutData?.sitecore?.context?.language,
        });
    
      return result;
    }

    See The Sitecore configuration file for more information.

  7. Export your component, wrapped in the withDatasourceCheck higher-order component:

    export default withDatasourceCheck()<ComponentProps>(GraphQLDemo);

Use the SitecoreClient's getData method

For apps that use Content SDK 1.2 or later, the SitecoreClient API exposes a simple, typed way to run raw GraphQL requests. It forwards your call to the SDK’s low-level GraphQLClient.request with the same retry, header, and fetch behavior you’ve configured.

Given below is the type signature of the getData method:

getData<T = unknown>( query: string | import('graphql').DocumentNode, variables?: Record<string, unknown>, fetchOptions?: FetchOptions ): Promise<T>

The following example retrieves results (id and name) where the name equals Home and the language is en:

type SearchResult = { search: { results: { id: string; name: string }[] } };

const res = await client.getData<SearchResult>(
  `
  query SearchByName($name: String!, $lang: String!) {
    search(where: { name: { equals: $name } }, language: $lang) {
      results { id name }
    }
  }`,
  { name: 'Home', lang: 'en' }
);

The following example uses the graphql-tag library to build the query and it retrieves results (id) where the language is en.

import { gql } from 'graphql-tag';

const Query = gql`
  query ($lang: String!) { search(language: $lang) { results { id } } }
`;

const res = await client.getData<{ search: { results: { id: string }[] } }>(Query, { lang: 'en' });
If you have suggestions for improving this article, let us know!