web-dev-qa-db-fra.com

React Apollo - Faites plusieurs requêtes

J'ai un fichier de requêtes qui ressemble à ceci:

import {gql} from 'react-apollo';

const queries = {
  getApps: gql`
    {
      apps {
        id
        name
      }
    }
  `,
  getSubjects: gql`
    {
      subjects {
        id
        name
      }
    }
  `
};

export default queries;

J'importe ensuite ce fichier dans mon composant React:

import React, {Component} from 'react'
import queries from './queries'

class Test extends Component {
...
}

export default graphql(queries.getSubjects)(graphql(queries.getApps)(Test));

Cela obtiendra uniquement des données pour l'une des requêtes (getApps) et non les deux. Si je fais un à la fois pour que cela ressemble à ceci:

export default graphql(queries.getSubjects)(Test);

alors cela fonctionne mais je n'ai pas mon autre requête. Oui, j'ai testé les deux séparément et ils fonctionnent. Comment puis-je l'obtenir afin que les deux requêtes apparaissent dans mes props.data?

23
user2465134

Ma méthode préférée consiste à utiliser la fonctionnalité compose du client apollo ( docu ).

EDIT: Si vous avez plusieurs requêtes, vous devez les nommer.

Donc, dans votre cas, cela pourrait ressembler à ceci:

import React, {Component} from 'react'
import queries from './queries'
import { graphql, compose } from 'react-apollo';

class Test extends Component {
...

  render() {
    ...
    
    console.log(this.props.subjectsQuery, this.props.appsQuery); // should show both 
    
    ...
  }
}

export default compose(
   graphql(queries.getSubjects, {
      name: "subjectsQuery"
   }),
   graphql(queries.getApps, {
      name: "appsQuery"
   }),
)(Test);

30
Locco0_0

Si vous ne souhaitez pas réutiliser aucune de ces requêtes indépendamment, pourquoi ne pas faire une seule demande en combinant les deux requêtes dans une seule:

const combinedQueries = gql`
{
  apps {
    id
    name
  }
  subjects {
    id
    name
  }
}
`

et alors vous pouvez l'utiliser dans votre composant

import React, {Component} from 'react'
import combinedQueries from './combinedQueries'

class Test extends Component {
   ...
   render() {
     ...
     if(!this.props.combinedQueries.loading) {
       console.log(this.props.combinedQueries.apps);
       console.log(this.props.combinedQueries.subjects);
     }
     ...
   }
}

export default graphql(combinedQueries, {name: 'combinedQueries'})(Test);
5
essaji

Pour Apollo 2.x: vous pouvez utiliser react-adopt pour composer les requêtes et les mutations en un seul niveau. (Cette bibliothèque composera tous les composants avec des accessoires de rendu, par exemple l’API de contexte React.)

https://github.com/pedronauck/react-adopt

4
Luke Williams

IMHO, une des solutions les plus soignées est décrite dans Implémentation Apollo Client React .
L'idée de base est de regrouper vos requêtes dans des composants Query imbriqués. L'utilisation de fonctions de fermeture en tant qu'enfants de composants facilite la délégation des résultats d'une requête à une autre, etc. 

 const QueryOne = gql`
  query One {
    one
  }
`;

const QueryTwo = gql`
  query Two {
    two
  }
`;

const NumbersWithData = () => (
  <Query query={QueryOne}>
    {({ loading: loadingOne, data: { one } }) => (
      <Query query={QueryTwo}>
        {({ loading: loadingTwo, data: { two }}) => {
          if (loadingOne || loadingTwo) return <span>loading...</span>
          return <h3>{one} is less than {two}</h3>
        }}
      </Query>
    )}
  </Query>
);
4
voogieJames

J'utilise réagis-adopte pour le faire. C'est vraiment simple et garder notre code propre.

Exemple simple:

import { adopt } from 'react-adopt';

...
render() {
  const Composed = adopt({
    first: ({ render }) => <Query query={FIRST_QUERY}>{ render }</Query>,
    second: ({ render }) => <Query query={SECOND_QUERY}>{ render }</Query>
  });

  return (
    <Composed>
      ({ first, second }) => {
        console.log('first', first)
        console.log('second', second)

        // validations (loading, error)

        return (
          <div>Your JSX</div>
        )
      }
    </Composed>
  )
}
...

Il y a beaucoup d'exemples utilisant

const Composed = adopt({
  first: <Query query={FIRST_QUERY} />,
  second: <Query query={SECOND_QUERY} />
});

Soyez prudent avec le composant <Query>, il a besoin d'enfants, sinon l'erreur suivante sera générée

Warning: Failed prop type: The prop children is marked as required in Query, but its value is undefined.

Pour éviter l'avertissement précédent, j'ai trouvé une solution possible:

first: ({ render }) => <Query query={FIRST_QUERY}>{ render }</Query>

J'espère que ça vous aide!

3
slorenzo

Une autre solution consiste à utiliser l'option props.

export default compose(
  graphql(QUERY_2, {
    props: ({ data }) => ({ ...data }),
  }),
  graphql(QUERY_1, {
    props: ({ data }) => ({ ...data, myCustomAttribute: data.foo }),
  }),
)(Component);

J'ai trouvé que cette approche est un peu plus intéressante pour mon cas d'utilisation.

Voici un lien vers la documentation: https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-props

0
user3812429

Une requête et une mutation utilisant la composition de react-apollo

Choses que j'ai conclues:

  1. Compose exécute ses requêtes de bas en haut.
  2. Les requêtes sont exécutées automatiquement, vous n'êtes pas obligé de les appeler, mais vous le faites avec des mutations.
  3. Il est évident que l'équipe Apollo souhaite que tout le monde utilise le composant Query plutôt que de composer. Par conséquent, je pense qu'il serait sage d'utiliser leur composant de requête comme ils le suggèrent, car ils risquent de rendre obsolète la composition plus tard.

Voici le code si vous voulez toujours utiliser compose:

import {gql} from 'graphql-tag'
import {graphql, compose} from 'react-apollo'
import React, {Component} from 'react'

const appQuery = gql`
    {
      apps {
        id
        name
      }
    }
  `

const subjectMutation = gql`
    mutation someName($name: String) {
      changeSubjects(name: $name) {
        subject {
          name
        }
      }
    }
  `
};

class Test extends Component {
...

  const MutationResponse = this.props.mutate({
    variables: {
      name: "some name"
    }
  })

  const QueryResponse = this.props.data.appQuery

...
}

export default compose(
  graphql(appQuery),
  graphql(subjectMutation) 
)(Test));
0
Isaac Pak