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?
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);
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);
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.)
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>
);
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!
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
Choses que j'ai conclues:
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));