graphql-tag icon indicating copy to clipboard operation
graphql-tag copied to clipboard

Add support for circular dependencies using thunks

Open migueloller opened this issue 7 years ago • 7 comments

When colocating fragments, circular dependencies often become an issue. While GraphQL doesn't support circular fragment dependencies, it is still possible to have circular dependencies in the component files that declare the fragments.

An example of this is when rendering a tree structure using GraphQL. While GraphQL doesn't allow for recursive queries, it is still possible to query an array of descendants and build a tree data structure in the client. This data structure can then be rendered recursively with React.

Pull Request Labels

  • [x] feature
  • [ ] blocking
  • [ ] docs

migueloller avatar Jul 31 '18 07:07 migueloller

@migueloller: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Meteor Contributor Agreement here: https://contribute.meteor.com/

apollo-cla avatar Jul 31 '18 07:07 apollo-cla

@migueloller it'd be useful to see a concrete example of how / what this changes — it's unclear to me when this logic would get applied

jnwng avatar Nov 14 '18 17:11 jnwng

@jnwng, something like this:

// file1.js
import { Fragment2 } from './file2.js'
import { Fragment3 } from './file2.js'

export const Fragment1 = () => gql`
  fragment Fragment1 on SomeType {
    field
    ...Fragment2
    ...Fragment3
  }

  ${Fragment2}
  ${Fragment3}
`

// file2.js
import { Fragment1 } from './file1.js'
import { Fragment3 } from './file2.js'

const SomeQuery = gql`
  query SomeQuery {
    foo {
      ...Fragment1
    }
  }

  ${Fragment1}
`

export const Fragment2 = () => gql`
  fragment Fragment2 on SomeType {
    field
    ...Fragment3
  }

  ${Fragment1}
  ${Fragment3}
`

// file3.js
export const Fragment3 = gql`
  fragment Fragment2 on SomeType {
    field
  }
`

Note that I could've also exported the fragment statically and put the thunk in the interpolation. The main idea is that interpolating in gql one could pass a DocumentNode (returned from gql) or a Thunk<DocumentNode>, where Thunk is defined like this:

type Thunk<T> = () => T

This change would be non-breaking I believe.

migueloller avatar Nov 14 '18 17:11 migueloller

Stumbled into the same issue.

It's usually "fixed" by avoiding eager compilations and using factories or something like that, but it is not possible in case of the graphql-tag coupled with babel-plugin-graphql-tag

ArmorDarks avatar Apr 10 '19 16:04 ArmorDarks

@jnwng @migueloller any progress on this?
This also makes something like this possible in ApolloClient.

HosseinAgha avatar Dec 30 '19 09:12 HosseinAgha

@HosseinAgha, happy to push this to the finish line if the Apollo team so desires! 😄

migueloller avatar Dec 30 '19 18:12 migueloller

@jnwng Apollo team please make this happen 🙏

HosseinAgha avatar Jan 12 '20 14:01 HosseinAgha