Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Relay Compatible `@defer` & `@stream`

Using @defer under an array field will return multiple patches. Patches are unique combinations of label and path

{
  items {
    id
    ...frag @defer(label: "my-label")
  }
}

fragment frag on Item {
  title
}

Initial result:

{
  "data": {
    "items": [
      { "id": 1 },
      { "id": 2 },
      { "id": 3 },
    ]
  }
}

Patches:

  • Multiple Patches
{
  "label": "my-label",
  "path": ["items", 0],
  "data": { "title": "chair" }
}
{
  "label": "my-label",
  "path": ["items", 1],
  "data": { "title": "table" }
}
{
  "label": "my-label",
  "path": ["items", 2],
  "data": { "title": "lamp" }
}

Fields that are on both deferred and non-deferred fragments are returned twice.

{
  item {
    title
    ...frag @defer(label: "my-label")
  }
}

fragment frag on Item {
  title
}

Initial result:

{
  "data": {
    "item": {
      "title": "chair"
    }
  }
}

Patch:

{
  "label": "my-label",
  "path": ["item"],
  "data": {
    "title": "chair" 
  }
}

Deferred fields are not returned at all in the initial response. This differs from the Apollo defer implementation, in which deferred fields are returned as null, and must be nullable in the schema.

{
  item {
    id
    ...frag @defer(label: "my-label")
  }
}

fragment frag on Item {
  title
}
  • Deferred field is not present
{
  "data": {
    "item": {
      "id": 1
    }
  }
}

Queries cannot contain the same field with multiple streams (or mix of stream and non-stream) without aliasing.

Not allowed:

query HeroNameQuery {
  hero {
    friends {
      id
    }
    ...FragA
    ...FragB
    
  }
}

fragment FragA on Character {
  friends @stream(label: "nameLabel", initial_count: 1) {
    name
  }
}

fragment FragB on Character {
  friends @stream(label: "appearsInLabel", initial_count: 2)  {
    appearsIn
  }
}

Allowed:

query HeroNameQuery {
  hero {
    friends {
      id
    }
    ...FragA
    ...FragB
    
  }
}

fragment FragA on Character {
  streamFriendsName: friends @stream(label: "nameLabel", initial_count: 1) {
    name
  }
}

fragment FragB on Character {
  streamFriendsAppearsIn: friends @stream(label: "appearsInLabel", initial_count: 2)  {
    appearsIn
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment