Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to declare fragment in functional component in Typescript? #2722

Closed
goldenbearkin opened this issue Dec 13, 2017 · 7 comments
Closed

How to declare fragment in functional component in Typescript? #2722

goldenbearkin opened this issue Dec 13, 2017 · 7 comments

Comments

@goldenbearkin
Copy link

I can easily declare a fragment in a class component by adding a static method.

export default class PokemonCard extends React.Component {

  static fragments = {
    pokemon: gql`
      fragment PokemonCardPokemon on Pokemon {
        url
        name
      }
    `
  }
  // ...
}

What is the best way to do the same in functional component in Typescript and pass the type checking?

PokemonCard.fragments = {
  pokemon: gql`
    fragment PokemonCardPokemon on Pokemon {
      url
      name
    }
  `,
};

screen shot 2017-12-13 at 11 00 24 pm

// error: 'fragments' does not exist on type 'typeof PokemonCard'

@danrasmuson
Copy link

My understanding (feedback welcome) is that doing ReactComponent.fragments is just a convention.

We put the fragment on CommentsPage.fragments.comment by convention, and use the familiar gql helper to create it.

I'm using typescript and I've decided to opt out of using fragments this way for exactly the reason you detailed above.

Instead I have a file devoted to a fragment...

file: queries/pokemon-card.fragment.tsx

export const PokemonCardFragment = gql`
    fragment PokemonCardPokemon on Pokemon {
      id
      url
      name
    }
`

Then in your query...

const getPokemonCardQuery = gql`
  query getPokemonCard($id:ID!){
     ...PokemonCardPokemon
  }
  ${PokemonCardFragment}
`

Lastly pro tip! Include id in your fragment query and anytime that fragment is fetched it will reload all components that use that fragment data.

I.E. if you have some mutation

mutation addCard($name: String!){
   addPokemonCard(name: $name){
      ... PokemonCardPokemon
   },
   ${PokemonCardFragment}
}

And as long as your mutation returns PokemonCardPokemon it will reload all components using that information.

@hwillson
Copy link
Member

@danielrasmuson's answer in #2722 (comment) is great! Closing - thanks!

@astorije
Copy link

Yeah, we ended up doing pretty much what @danielrasmuson described, except we colocate the fragment with the component, and use default and non-default exports to use this pattern:

// In PokemonCard.tsx:

const PokemonCard: SFC = () => <span />;

export default PokemonCard;

export const PokemonCardFragment = gql`
  fragment PokemonCardPokemon on Pokemon {
    id
    url
    name
  }
`;

// In the caller file:

import PokemonCard, { PokemonCardFragment } from './PokemonCard'; // <-- This is the main difference in usage

const GET_POKEMON_CARD_QUERY = gql`
  query getPokemonCard($id: ID!) {
    ...PokemonCardPokemon
  }
  ${PokemonCardFragment}
`;

@fabientownsend
Copy link

fabientownsend commented Jan 4, 2021

I came across the same issue, one approach is to extend the interface FunctionComponent provided by React, for example:

import { FunctionComponent } from 'react'

interface FCWithFragment<E> extends FunctionComponent<E> {
  fragment: string
}

type YourComponentProps = {}
export const YourComponent: FCWithFragment<YourComponentProps> = (props) => {
  return ... 
}

YourComponent.fragment = gql`
...
`

@goughjo03
Copy link

I came across the same issue, one approach is to extend the interface FunctionComponent provided by React, for example:

import { FunctionComponent } from 'react'

interface FCWithFragment<E> extends FunctionComponent<E> {
  fragment: string
}

type YourComponentProps = {}
export const YourComponent: FCWithFragment<YourComponentProps> = (props) => {
  return ... 
}

YourComponent.fragment = gql`
...
`

Is this really necessary? Apollo client hasn't thought of this already?

@josecolella
Copy link

@goughjo03 has there been any updates to this. Running across this in my project and wondering if there's a solution

@goughjo03
Copy link

@josecolella they are planning to develop a useFragment hook and there is an issue to track it here #8236

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants