J'utilise le <Query>
d'Apollo Client dans un composant qui est rendu à nouveau lorsque l'état est modifié dans une méthode de cycle de vie. Je souhaite que mon composant <Query>
ré-exécute la requête car je sais que les données ont été modifiées .. Il apparaît que le composant Query utilise un cache qui doit être invalidé avant que la requête ne soit réexécutée.
J'utilise une solution de contournement qui met en cache le rappel refetch
à partir de l'accessoire de rendu dans le composant parent, mais cela semble faux. Je posterai mon approche dans les réponses si quelqu'un est intéressé.
Mon code ressemble à quelque chose comme ça. J'ai supprimé les manipulations loading
et error
de la requête ainsi que certains autres détails par souci de concision.
class ParentComponent extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.refetchId !== prevProps.refetchId) {
const otherData = this.processData() // do something
this.setState({otherData}) // this forces component to reload
}
}
render() {
const { otherData } = this.state
return (
<Query query={MY_QUERY}>
{({ data }) => {
return <ChildComponent gqlData={data} stateData={otherData} />
}}
</Query>
)
}
}
Comment forcer <Query>
à récupérer de nouvelles données à transmettre à <ChildComponent>
?
Même si ParentComponent
effectue un nouveau rendu lorsque les accessoires ou les états changent, Query
ne s'exécute pas à nouveau. ChildComponent
obtient une prop stateData
mise à jour, mais a une prop gqlData
obsolète. Si j'ai bien compris, le cache de requêtes d'Apollo doit être invalidé, mais je ne suis pas sûr.
Notez que transmettre refetch
à ChildComponent n’est pas la solution car il n’affiche que les informations provenant de GraphQL et ne sait pas quand récupérer. Je ne veux pas introduire de timers ni autrement compliquer ChildComponent
pour résoudre ceci - il n'a pas besoin de connaître cette complexité ni les problèmes d'extraction de données.
Il me semble que le composant Query n'a pas nécessairement besoin d'être dans cette ParentComponent
.
Dans ce cas, je déplacerais le composant de requête vers le haut, étant donné que je serais toujours capable de restituer d'autres éléments sans avoir de résultats dans la variable ChildComponent
. Et puis j'aurais accès à la méthode query.refetch
.
Notez que dans l'exemple, j'ai ajouté graphql
hoc, mais vous pouvez toujours utiliser le composant Query autour de <ParentComponent />
.
class ParentComponent extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.refetchId !== prevProps.refetchId) {
const otherData = this.processData() // do something
// won't need this anymore, since refetch will cause the Parent component to rerender)
// this.setState({otherData}) // this forces component to reload
this.props.myQuery.refetch(); // >>> Refetch here!
}
}
render() {
const {
otherData
} = this.state;
return <ChildComponent gqlData={this.props.myQuery} stateData={otherData} />;
}
}
export graphql(MY_QUERY, {
name: 'myQuery'
})(ParentComponent);
Pourriez-vous récupérer dans le composant parent? Une fois que le composant parent a obtenu une mise à jour, vous pouvez alors déterminer s'il faut déclencher une extraction ou non.
Je l'ai fait sans utiliser Query
comme ceci:
class ParentComp extends React.Component {
lifeCycleHook(e) { //here
// call your query here
this.props.someQuery()
}
render() {
return (
<div>
<Child Comp data={this.props.data.key}> //child would only need to render data
</div>
);
}
}
export default graphql(someQuery)(SongCreate);
Ainsi, vous pouvez déclencher votre recherche à tout moment. Vous pouvez obtenir la requête sous la forme prop
dans ce cas.
Pour votre cas, vous mettriez votre requête dans un accessoire utilisant export default graphql(addSongQuery)(SongCreate);
. Ensuite, appelez-le dans votre cycle de vie crochet_sans DidUpdate
.
Une autre option consiste à utiliser refetch
sur une requête.
<Query
query={GET_DOG_PHOTO}
variables={{ breed }}
skip={!breed}
>
{({ loading, error, data, refetch }) => {
if (loading) return null;
if (error) return `Error!: ${error}`;
return (
<div>
<img
src={data.dog.displayImage}
style={{ height: 100, width: 100 }}
/>
<button onClick={() => refetch()}>Refetch!</button>
</div>
);
}}
</Query>
La deuxième méthode exigerait que vous transmettiez quelque chose à votre enfant, ce qui n’est pas si grave.