How to force Apollo Query component to re-run query when parent component re-renders
I had almost a similar situation which I solved with fetchPolicy
attribute:
<Query fetchPolicy="no-cache"
...
The task was to load some details from server by clicking on a list item.
And if I wanted to add an action to force re-fetching the query (such as modifying the details), I first assigned the refetch
to this.refetch
:
<Query fetchPolicy="no-cache" query={GET_ACCOUNT_DETAILS} variables=... }}> {({ data: { account }, loading, refetch }) => { this.refetch = refetch;...
And in the specific action that I wanted the refetch to happen, I called:
this.refetch();
It seems to me that the Query component doesn't necessarily need to be inside this ParentComponent
.
In that case, I would move the Query component up, since I would still be able to render other stuff while I don't have results in the ChildComponent
. And then I would have access to the query.refetch
method.
Note that in the example I added the graphql
hoc, but you can still use Query component around <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);
Could you refetch in parent component? Once the parent component get an update, then you can evaluate whether to trigger a fetch or not.
I have done it without using Query
like the following:
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);
So you can trigger your fetch anytime you want it to. You can get the query as a prop
in this case.
For your case, you would put your query into a prop using export default graphql(addSongQuery)(SongCreate);
. Then call it in your lifecyclehooks DidUpdate
.
Another options is to use refetch
on Query.
<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>
The second method would require you pass something down to your child, which isn't really all that bad.