Supposons que j'ai la requête GraphQL suivante dans React-Apollo
const CurrentUserForLayout = gql`
query CurrentUserForLayout($avatarID: Int!) {
currentUser {
avatar_url(avatarID: $avatarID)
}
}
`;
const ProfileWithData = graphql(CurrentUserForLayout, {
options: { variables: { avatarID: 1 } },
})(Profile);
Maintenant, si je veux laisser mon React component Profile
changer le avatarID,
comment pourrais-je faire ça?
Je suis nouveau sur React et GraphQl et je ne comprends pas vraiment la connexion ici:
graphql(CurrentUserForLayout, {
options: { variables: { avatarID: 1 } },
})(Profile);
Ai-je vraiment besoin d'un autre composant parent autour de ProfileWithData
pour passer un autre avatarID
à la requête? Mais que se passe-t-il si l'ID est manipulé par le composant Profil, comment puis-je en informer le composant Parent?
Jusqu'à présent, je connais deux approches possibles à cela.
Le premier est déjà indiqué dans la question. Les variables sont en même temps les accessoires du ProfileWithData
. Vous devez donc trouver un moyen de modifier les accessoires et de restituer le composant. Ceci est généralement réalisé avec un composant parent. Donc, généralement, vous ne modifiez pas les variables à l'intérieur de ProfileWithData
. Ce composant ne doit être utilisé qu'à des fins d'affichage. Cependant, cela ne signifie pas que cela ne peut pas être fait. Vous pouvez transmettre les méthodes de votre composant parent à l'enfant afin de manipuler l'état du parent. Cela rendra les deux composants et rendra le ProfileWithData
avec de nouveaux accessoires/variables.
La deuxième approche consiste à interroger depuis l'intérieur du composant ProfileWithData
. Vous pouvez ensuite manipuler les variables de l'intérieur du composant avec l'état. Une méthode pour ce faire peut être trouvée ici
Vous pouvez le faire en transmettant une référence à Apollo Client en utilisant le composant d'ordre supérieur
withApollo
, comme indiqué ici: http://dev.apollodata.com/react/higher-order-components .html # withApolloEnsuite, vous pouvez appeler
client.query
sur l'objet passé, comme ceci:class MyComponent extends React.Component { runQuery() { this.props.client.query({ query: gql`...`, variables: { ... }, }); } render() { ... } } withApollo(MyComponent);
Avant Apollo Client 2.1
Avant Apollo Client 2.1, lorsque vous deviez utiliser Composants d'ordre supérieur (HOC), il y avait deux solutions qui étaient correctement signalées par henk dans l'autre réponse. J'essaie de les résumer brièvement:
Étant donné que le HOC n'a accès qu'aux accessoires, vous devez introduire la variable changeante dans votre composant parent. Par exemple, le composant parent pourrait avoir une gestion d'état locale en place pour la variable changeante avec la méthode setState()
de React. Une fois que la variable change dans l'état local, elle peut être transmise à votre autre composant qui est amélioré par le HOC. Le HOC a accès aux accessoires et peut exécuter la requête avec une variable modifiée. Astuce: Si vous ne voulez pas introduire un autre composant entre les deux pour changer l'état local, recomposer 's withState
HOC pourrait être un excellent choix.
La deuxième façon, mais peut-être moins élégante, car elle fait passer votre code de déclaratif à impératif, serait d'utiliser la fonction withApollo()
HOC qui vous donne accès à l'instance du client Apollo comme accessoire. En ayant cette instance dans votre composant React, vous pouvez appeler client.query({ query: ..., variables: ... })
dans l'une des méthodes de classe de votre composant (par exemple onChange
handler) une fois que votre variable change.
Depuis Apollo Client 2.1
Depuis Apollo Client 2.1 vous pouvez utiliser le nouveau composant Query (and Mutation). Le HOC existe toujours, mais n'est plus annoncé par le documentation . Cependant, le nouveau composant Requête (et mutation) est utilisé dans votre composant. Il utilise le modèle d'accessoires de rendu de React.
import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";
const GET_TODOS = gql`
{
todos {
id
type
}
}
`;
const Todos = () => (
<Query query={GET_TODOS}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return data.todos.map(({ id, type }) => (
<p key={id}>{type}</p>
));
}}
</Query>
);
En déplaçant ce flux de contrôle à l'intérieur du composant plutôt que de l'avoir uniquement co-localisé avec un HOC, vous pouvez transmettre l'hélice changeante en tant que variable à votre composant Requête (et mutation).
import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";
const TOGGLE_TODO = gql`
mutation ToggleTodo($id: Int!) {
toggleTodo(id: $id) {
id
completed
}
}
`;
const Todo = ({ id, text }) => (
<Mutation mutation={TOGGLE_TODO} variables={{ id }}>
{(toggleTodo, { loading, error, data }) => (
<div>
<p onClick={toggleTodo}>
{text}
</p>
{loading && <p>Loading...</p>}
{error && <p>Error :( Please try again</p>}
</div>
)}
</Mutation>
);
Si vous voulez apprendre Apollo Client dans React, passez à la caisse ce didacticiel détaillé . Remarque: les extraits de code sont extraits du billet de blog de la version Apollo Client 2.1.
Votre composant ProfileWithData
fait un bon travail de rendu de l'avatar d'un certain utilisateur. Ce n'est pas la responsabilité de ce composant de gérer les modifications du composant avatar actuellement affiché.
Une façon consiste à ajouter un nouvel accessoire avatarId
qui est transmis du composant parent. Ensuite, vous devrez écrire ceci:
graphql(CurrentUserForLayout, {
options: (ownProps) => ({
variables: {
id: ownProps.avatarId
}
})
})(Profile);
Si vous connaissez react-router
, une autre approche consisterait à utiliser les paramètres de l'itinéraire pour déterminer l'identifiant de l'avatar. Vous devrez ajuster l'appel de graphql
comme ceci:
graphql(CurrentUserForLayout, {
options: (ownProps) => ({
variables: {
id: ownProps.params.avatarId
}
})
})(Profile);
Pour en savoir plus sur l'utilisation de variables de requête comme celle-ci, vous pouvez consulter le React Track of Learn Apollo .