Use GraphQL to fetch component-level data in JSS Next.js apps

Current version: 22.0

The Next.js sample app supports component-level data fetching , enabling querying GraphQL endpoints at the component level.

Note

If you include secrets or sensitive information in component-level getStaticProps and getServerSideProps functions, that information will only be included in the client-side bundle in development mode.

The sample app provides a GraphiQL interface for exploring the schema and testing queries. By default, the interface can be accessed using ${SITECORE_API_HOST}/sitecore/api/graph/edge/ui?sc_apikey=${SITECORE_API_KEY}. This interface is helpful if you want to determine what GraphQL types can be used by your components.

Note

The graphql-let library provides the same information about types in the corresponding .graphq.d.ts files.

To use component-level data fetching with GraphQL:

  1. In a GraphQL-ConnectedDemo.dynamic.graphql file, define a GraphQL query. For example:

    RequestResponse
    
    query ConnectedDemoQuery($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
        # Strongly-typed querying on known templates is possible!
        ...on GraphQLConnectedDemo {
          # Single-line text field
          sample1 {
            # the 'jsonValue' field is a JSON blob that represents the object that
            # should be passed to JSS field rendering helpers (i.e. text, image, link)
            jsonValue
            value
          }
          # General Link field
          sample2 {
            jsonValue
            # Structured querying of the field's values is possible
            text
            target
            url
            # Access to the template definition is possible
            definition {
              type
              shared
            }
          }
        }
      }
    
      # 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 app route template
        ...on AppRoute {
          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 AppRoute {
              pageTitle {
                jsonValue
                value
              }
            }
            url{
              path
            }
          }
        }
      }
    }
    

    The library graphql-let generates a file GraphQLDemoQuery.graphql.d.ts.

  2. In your component file, add the following import statements:

    RequestResponse
    
    import React, { useEffect } from 'react';
    import {
      Text,
      Link,
      GetServerSideComponentProps,
      GetStaticComponentProps,
      constants,
      withDatasourceCheck,
    } from '@sitecore-jss/sitecore-jss-nextjs';
    import { GraphQLRequestClient } from '@sitecore-jss/sitecore-jss-nextjs/graphql';
    import {
      resetEditorChromes
    } from '@sitecore-jss/sitecore-jss-nextjs/utils';
    import { ComponentProps } from 'lib/component-props';
    import config from 'temp/config';
    
  3. If needed, update your introspection data to have access to the latest GraphQL types.

  4. Import your GraphQL query and GraphQL types:

    RequestResponse
    
    import { ConnectedDemoQueryDocument } from './GraphQL-ConnectedDemo.dynamic.graphql';
    import {
      AppRoute as AppRoute,
      Item,
      GraphQlConnectedDemo as GrapQLConnectedDemoDatasource,
    } from 'graphql-types';
    
    
  5. Define your TypeScript types and the GraphQLDemo component:

    RequestResponse
    
    type RouteItem = AppRoute & Item;
    
    type GraphQLConnectedDemoData = {
      datasource: GrapQLConnectedDemoDatasource;
      contextItem: RouteItem;
    };
    
    type GraphQLConnectedDemoProps = ComponentProps & GraphQLConnectedDemoData;
    
    const GraphQLConnectedDemo = (props: GraphQLConnectedDemoProps): JSX.Element => {
      useEffect(() => {
        resetEditorChromes();
      }, []);
    
      return (
        // your markup
      );
    };
    
  6. In your component, define getStaticProps or getServerSideProps functions. The following example implements the getStaticProps function. Because GraphQL does not work in disconnected mode, you must exit the function if the app runs in disconnected mode. You must also create a new GraphQL client using the GraphQLRequestClient class. For example:

    RequestResponse
    
     export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData) => {
        const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {    
            apiKey: config.sitecoreApiKey,  
          });
     } 
    
  7. Perform the request and return the result:

    RequestResponse
    
    export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData) => {
      const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {
        apiKey: config.sitecoreApiKey,
      });
      const result = await graphQLClient.request<GraphQLConnectedDemoData>(
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        ConnectedDemoQueryDocument as any,
        {
          datasource: rendering.dataSource,
          contextItem: layoutData?.sitecore?.route?.itemId,
          language: layoutData?.sitecore?.context?.language,
        }
      );
      return result;
    };
    
  8. Export your component, wrapped in the withDatasourceCheck higher-order component:

    RequestResponse
    
    export default withDatasourceCheck()&lt;ComponentProps&gt;(GraphQLConnectedDemo);
    
Tip

If you're building a very large website using the Sitecore XM Cloud, you might have to enable retries for requests to the XM Cloud Experience Edge GraphQL endpoint for the build process to complete.

Do you have some feedback for us?

If you have suggestions for improving this article,