Intended outcome:
When setting variables on the <Query> component via props or state, updating those variables should just update the props of the children.
eg if i keep variables in parent state and pass a handler down to Query's children:
<Query query={QUERY} variables={this.state.someVariables}>
{({loading, data, error}) => (<SomeStatefulComponent
changeParentStateVar={
(newVars) => this.setState(() => ({someVariables: newVars}) )
}
data={data} />
)
}
</Query>
Actual outcome:
The children of Query are unmounted and re-mounted, erasing any internally held state and even triggering willUnmount / willMount lifecycle methods.
It looks like this only happens on a cache miss, though--ie only when apollo has to hit the network for a query / var combination.
How to reproduce the issue:
set Query's variables to parent state, then update that state.
add this to render children if you like
componentWillUnmount() {
console.log('Unmounting');
}
componentWillMount() {
console.log('Mounting');
}
Version
also:
reverting to the graphql HOC pattern & calling data.refetch() works fine
Still an issue in 2.1.3, cannot use local state in childrens of a query if i need to update variables, very limiting
HOC now uses Query under the hood, so it is broken
@jbaxleyiii any escape hatch you are aware of?
HOC now uses Query under the hood, so it is broken
oh wow, thanks for pointing that out. i recently upgradedreact-apolloand somehow didn't notice that
i haven't dug into react-apollo src yet but is there any obvious reason why this works this way? no other renderProp components I use share this behavior
This also means refs are destroyed AFAIK so sibling components using refs from the component that was remounted are gone.
Issue exists even after updating to 2.1.6.
I have a table of paged data with filters at the top. When the filter is changed, the query variables are updated. Everything below the Query component gets remounted / reconstructed.
Pretty serious, IMO.
Can you paste your component? If you switch out the parents based on loading, then it will change the whole tree downstream.
If you switch out the parents based on loading, then it will change the whole tree downstream.
That was precisely the issue. Thanks!
Anyone found a fix for this ?
One day tracing this bug... any fix?
I thought one of the major selling points of Query components was to use state in the component vs having to create a parent component to hold state (or redux)?
I have same problem. Now i save data from graphql response into component state if data has changed.
It is terrible solution, but it works. Waiting for fix.
renderQuery = () => (
<Query query={QUERY} variables={this.state.someVariables}>
{({loading, data, error}) => {
if (data == this.state.data) return <View />;
setTimeout(() => {
this.setState({
myData: data,
});
};
return <View />
}
}
</Query>
)
renderChildren = () => (
<SomeStatefulComponent data={this.state.data} />
)
render() {
return (
{this.renderQuery}
{this.renderChildren}
)
}
I think @cranberyxl has this right already - missed that on the first pass:
If you switch out the parents based on loading, then it will change the whole tree downstream.
I think this is still an issue, or am i missing something?
If you switch out the parents based on loading, then it will change the whole tree downstream.
Do you see any logic based on loading in @brandonmp example up there? This is occuring even if the Query render logic is simple - like always returning some dummy component without any props. The remounting occurs right in the moment when Query variables changes.
Any update on this?
I'm also seeing this behavior...under certain conditions (the Query component's query is also configured as a refetchQueries query on a mutation update and the mutation is called) the child component is re-instantiated and thus all previously held local state blown away. I can try mitigate this by passing state in as props from the parent component but I still get a flash (which I think is the dom for the child being rebuilt)
@rosskevin this does seem like an issue...would you mind explaining why it does this and perhaps what can be done to mitigate it?
Most helpful comment
Can you paste your component? If you switch out the parents based on
loading, then it will change the whole tree downstream.