12

Let's say I have a page builder field that references many different types of content blocks.

  • Video
  • Quote
  • Advertisement

etc...

From what I've read, having multiple types in an array is discouraged.

But what else are you supposed to do in a case like this?

Is there a way to handle this in GraphQL?

Is there a better way to structure the data?

Andrew Folts
  • 489
  • 1
  • 5
  • 9

2 Answers2

21

You could define them as a union (or interface if all implementing types share common fields)

Union schema example:

type Query {
  blocks: [ ContentBlock! ]!
}

type Video {
  url: String!
}

type Quote {
  body: String!
  author: String
}

type Advertisement {
  src: String!
  backgroundColor: String
}


union ContentBlock = Video | Quote | Advertisement

Interface schema example:

type Query {
  blocks: [ ContentBlock! ]!
}

type Video implements ContentBlock {
  id: ID!
  url: String!
}

type Quote implements ContentBlock {
  id: ID!
  body: String!
  author: String
}

type Advertisement implements ContentBlock {
  id: ID!
  src: String!
  backgroundColor: String
}


interface ContentBlock {
  id: ID!
}

Example resolver:

{
  ContentBlock: {
    __resolveType (source) {
      if (source.url) return 'Video'
      if (source.src) return 'Advertisment'
      if (source.author || source.body) return 'Quote'
    }
  }
}

Example query:

{
  blocks {
    ...on Video {
      url
    }
    ...on Quote {
      body
      author
    }
    ...on Advertisement {
      src
      backgroundColor
    }
  }
}

More reading on Unions and Interfaces in GraphQL

E. Serrano
  • 4,634
  • 1
  • 18
  • 15
Seth
  • 490
  • 2
  • 7
1

i believe, that you can implement a list of interfaces or list of unions (based on the nature of data and if there are recurring fileds). And in that interface/union you will implement all these types (Video, Quote, Advertisement). However it will work for data fetching, but interfaces or unions are not avaialable as input types. If you would like to implement it as input type, you would need to use for example JSON custom scalar https://github.com/taion/graphql-type-json for it.

Edit: I do not thing that having multiple types in the list within interface is bad practice. You can take a look on nodes query or search on Github api https://developer.github.com/v4/query/

David Mraz
  • 545
  • 4
  • 8