How do I apply DRY principle on "links" field of Structured Text?

Hi,

I am using GraphQL CDA on the frontend. And I am using GraphQL fragments on the blocks field of Structured Text and it is working great.

Now, I enabled linking of inline records in Structured Text and I am fetching links fields like this:

query getSingleCoursePage($slug: String!) {
          course(filter: { slug: { eq: $slug } }) {
            id
            slug
            pageContent {
              blocks {
                ...FAQCollectionBlockFields
                ...SplitPaneBlockFields
              # trimmed for brevity
              }
              links {
                 ... on CourseOverviewPageRecord {
                  id
                  _modelApiKey
                  slug
                }
                ... on AboutPageRecord {
                  id
                  _modelApiKey
                }
              # trimmed for brevity
              }
              value
            }
}

And I’m using Structured Text on multiple other places in the project. Another example is:

fragment BrownSplitPaneBlockFields on BrownSplitPaneRecord {
    id
    _modelApiKey
    leftSection {
      blocks {
        ...FAQCollectionBlockFields
      }
      links
      value
    }
    rightSection {
      blocks {
        ...FAQCollectionBlockFields
      }
      links {
        ... on CourseOverviewPageRecord {
          id
          _modelApiKey
          slug
        }
        ... on AboutPageRecord {
          id
          _modelApiKey
        }
       # trimmed for brevity
      }
      value
    }
}

As you see that I’m repeating the code in the links field of Structured Text.

So, my question is how can I fetch this data without repeating code?

PS: I need this links query on at least 10 other places in my codebase.

Thanks!!!

Hello @itsahmedkamal

You can use GraphQL fragments for this, to avoid code repetition:

Hi @m.finamor, thank you for the reply.

I have been using Fragments for the blocks and that’s working perfectly fine.

But, I couldn’t figure out how can I use Fragments here when I don’t know the type.

If you don’t mind, can you please create a fragment from one of the code snippets I shared?

That would be very helpful.

Thank you!

Hello @itsahmedkamal

It would be something like:

query getSingleCoursePage {
  course {
    id
    slug
    pageContent {
      ...pageContentFragment
    }
  }
}

fragment pageContentFragment on CourseModelPageContentField {
  links {
    ... on CourseOverviewPageRecord {
      id
      _modelApiKey
      slug
    }
    ... on AboutPageRecord {
      id
      _modelApiKey
    }
  }
  value
}

If you don’t know the type of a parent field, you can just hover it on our query explorer, and you will see its type name right away:

Let me know if that solves your issue

Thank you so much for providing me the code snippet.

It definitely helped a lot.

But it doesn’t solve the problem fully.

On the Fragment definition, we write ā€œon CourseModelPageContentFieldā€ - it works when we use it on pageContent - but it doesn’t work when we use it on BrownSplitPaneRecord - because we have hard coded type CourseModelPageContentField on fragment definition.

Hello @itsahmedkamal I see,

In that case due to the type safety it is not possible unfortunately to re-use the same fragment on two different models of two different types at the moment

So the same fragment would have to be duplicated with a ā€œon BrownSplitPaneRecordā€ and another with ā€œon CourseModelPageContentFieldā€ :frowning:

ok, I got it. Thank you for help.

I’m just pasting my temporary solution below that can be useful for future readers.

I’ve created a file called fragments.js - and I’ve declared these fragments there.

import { gql } from 'graphql-request';

export const COURSE_OVERVIEW_PAGE_LINK_FIELDS = gql`
  fragment CourseOverviewPageLinkFields on CourseOverviewPageRecord {
    id
    _modelApiKey
    slug
  }
`;

export const ABOUT_PAGE_LINK_FIELDS = gql`
  fragment AboutPageLinkFields on AboutPageRecord {
    id
    _modelApiKey
  }
`;

And I am using it like this on queries.

query getSingleCoursePage($slug: String!) {
          course(filter: { slug: { eq: $slug } }) {
            id
            slug
            pageContent {
              blocks {
                ...FAQCollectionBlockFields
                ...SplitPaneBlockFields
              # trimmed for brevity
              }
              links {
                ...CourseOverviewPageLinkFields
                ...AboutPageLinkFields
              # trimmed for brevity
              }
              value
            }
}

And please don’t forget to import those fragments in the file where you are writing this query.

And add fragments like these on the end of graphql-reuqest query.

${COURSE_OVERVIEW_PAGE_LINK_FIELDS}
${ABOUT_PAGE_LINK_FIELDS}
1 Like