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

Current version: 19.x

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

Note

Following the code-first developer workflow, you can run GraphQL component-level queries only in connected mode.

Danger

Component-level getStaticProps and getServerSideProps functions are included in the client-side bundle. Any imports they depend on are also included in the client-side bundle, even if the client-side code does not use the imports.

Do not include any secrets, or sensitive information you don't want to expose.

This does not affect page-level getStaticProps and getServerSideProps functions.

In the code, it is a good practice to have strong types connected to GraphQL types defined in the Sitecore GraphQL Edge endpoint. To achieve this, the application uses the library graphql-let and GraphQL introspection data.

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.graphql file, define a GraphQL query following the Connected Demo query example.

    The library graphql-let generates a file GraphQL-ConnectedDemoQuery.graphql.d.ts.

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

    RequestResponsetypescript
    import {
      GetServerSideComponentProps,
      GetStaticComponentProps,
      useComponentProps,
      GraphQLRequestClient} from '@sitecore-jss/sitecore-jss-nextjs';
  3. Import your GraphQL query. graphql-let provides the ability to import queries.

    RequestResponsetypescript
    import {
      ConnectedDemoQueryDocument,
      AppRoute,
      Item,
      GraphQlConnectedDemo as GrapQLConnectedDemoDatasource,} from './ConnectedDemoQuery.graphql';
  4. In your component, define the getStaticProps or getServerSideProps functions. In this example, we implement getStaticProps. 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:

    RequestResponsetypescript
     export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData) => {
        if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {    
            return null;  
        }
        const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {    
          apiKey: config.sitecoreApiKey,  
        });
     } 
  5. Perform the request and return the result:

    RequestResponsetypescript
    export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData) => {
      if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
        return null;  
      }
      const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {
        apiKey: config.sitecoreApiKey,
      });
      const result = await graphQLClient.request<GraphQLConnectedDemoData>(MyQuery, {
        datasource: rendering.dataSource,
        contextItem: layoutData?.sitecore?.route?.itemId,
        language: layoutData?.sitecore?.context?.language,
      });
      return result;
    };
  6. In your component function, you can access the resulting data using the useComponentProps hook:

    RequestResponsetypescript
    const GraphQLConnectedDemo = (props: StyleguideComponentProps): JSX.Element => {
      const data = useComponentProps<GraphQLConnectedDemoData>(props.rendering.uid);
      // implement your component
    }
  7. Implement a strategy for showing content in editing mode. You can use the Sitecore context to render static data. Alternatively, to see master database data in editing mode, instantiate the GraphQL client with the endpoint URL for the Content Management instance.

    Note

    If you omit this step, the application displays the same data in editing mode as it does for site visitors because the Content Delivery URL endpoint serves from the web rather than the master database.

    • To render placeholder markup in your component:

      RequestResponsetypescript
      import { useSitecoreContext} from '@sitecore-jss/sitecore-jss-nextjs';
      
      const MyComponent = () => {
        const { sitecoreContext } = useSitecoreContext(); 
        // define some stub data
        if (sitecoreContext.pageEditing) {
          return (
            <div>
             This would usually render dynamic GraphQL data. This stub is used only for editing mode.
            </div>
          );
        }
        // ... rest of the component  
      }
    • To use a different endpoint for data fetching, check if the component is in preview/edit mode, and switch the URL accordingly. In this example, we assume you assigned your GraphQL editing URL to an environment variable named EDITING_GQL_ENDPOINT.

      RequestResponsetypescript
      export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData, context) => {
      
        if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
          return null;  
        }
        
        const {preview} = context;
        const graphQLEndpoint = preview ? process.env.EDITING_GQL_ENDPOINT : config.graphQLEndpoint;
      
        // if using getServerSideProps, you can use the Sitecore context from the layoutData
        // const graphQLEndpoint = layoutData.sitecore.context.pageEditing ? process.env.EDITING_GQL_ENDPOINT : config.graphQLEndpoint;
        
        const graphQLClient = new GraphQLRequestClient(graphQLEndpoint, {
          apiKey: config.sitecoreApiKey,
        });
      
        const result = await graphQLClient.request<GraphQLConnectedDemoData>(MyQuery, {
          datasource: rendering.dataSource,
          contextItem: layoutData?.sitecore?.route?.itemId,
          language: layoutData?.sitecore?.context?.language,
        });
      
        return result;
      };
      Note

      The sitecoreApiKey can differ between endpoints so make sure you switch it using a logic similar to switching the endpoint.

For a more complex example of using GraphQL queries in components, see the demo component in the JSS Next.js sample app.

Do you have some feedback for us?

If you have suggestions for improving this article,