Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you handle an array of multiple types (ex: different content blocks) in GraphQL?

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?

like image 548
Andrew Folts Avatar asked Aug 30 '18 01:08

Andrew Folts


People also ask

What are the three types of operations in GraphQL?

GraphQL works by sending operations to an endpoint. There are three types of operations: queries, mutations, and subscriptions.

What other types can be used in a GraphQL schema?

The GraphQL schema language supports the scalar types of String , Int , Float , Boolean , and ID , so you can use these directly in the schema you pass to buildSchema . By default, every type is nullable - it's legitimate to return null as any of the scalar types.


2 Answers

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

like image 96
Seth Avatar answered Sep 28 '22 04:09

Seth


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/

like image 37
David Mraz Avatar answered Sep 28 '22 04:09

David Mraz