Skip to content

Would it be possible to use Fragments just for pure re-usability? (without forced parent-child component encapsulation) #76

@rellampec

Description

@rellampec

In regards to the ImplicitlyFetchedFieldError, that is raised in GraphQL::Client::Schema::ObjectType, on method_missing...

              if @data.key?(field.name)
                raise ImplicitlyFetchedFieldError

Would it be possible to have the option to use fragments just for re-usability?

For example, in the Apollo documentation on fragments, it states that

Image

the main reason for fragments to exist is re-usability. It certainly emphasizes that it is specially useful when collocating with components, but it does NOT say that this is the only usage that we should be able to make out of it.

In the documentation (see collocated fragments), somehow states that there are two types of fragments, the ones that are "externally" (or collaterally) referred to by a component, and the ones that are defined right on that component (collated):

A colocated fragment is just like any other fragment, except it's defined in the same file as a particular component that uses the fragment's fields.

After you define a fragment in a child component, the parent component can refer to it in its own colocated fragments, like so:

export const FEED_ENTRY_FRAGMENT = gql`
  fragment FeedEntryFragment on FeedEntry {
    commentCount
    repository {
      full_name
      html_url
      owner {
        avatar_url
      }
    }
    ...VoteButtonsFragment
    ...EntryInfoFragment
  }

  ${VOTE_BUTTONS_FRAGMENT}
  ${ENTRY_INFO_FRAGMENT}
  • In this example VOTE_BUTTONS_FRAGMENT and ENTRY_INFO_FRAGMENT are defined in (or imported from) child components.
Image

Apollo's technique to define fragments and identify if they belong to a parent or children classes can arguable, yet they offer a way.


Following the example of graphlient gem, where fragments support was added by making it aligned with graphql-client, in the following query...

module Fragments
  Invoice = client.parse <<~'GRAPHQL'
    fragment on Invoice {
      id
      feeInCents
    }
  GRAPHQL
end

invoice_query = client.parse do
  query do
    invoice(id: 10) do
      id
      ___Fragments__Invoice
    end
  end
end

... we would get the error if trying to access feeInCents directly from the query Response

response = client.execute(invoice_query)
result = response.data.invoice
result.to_h
# {"id" => 10, "feeInCents"=> 20000}
result.id
# 10
result.fee_in_cents
# raises GraphQL::Client::ImplicitlyFetchedFieldError

How would we in graphql-client define a fragment that belongs to the main query (or parent component)?

  invoice_query <<~'GRAPHQL'
    query InvoiceById($some_id: Int) {
      invoice(id: $some_id) {
        id
        ...withFee
      }
    }

    fragment withFee on Invoice {
      id
      feeInCents
    }
  GRAPHQL

provided that we can do something like this:

response = client.execute(invoice_query)
result = response.data.invoice
result.fee_in_cents

without getting the error GraphQL::Client::ImplicitlyFetchedFieldError.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions