This seems related to #170, but I think it'll be something much simpler to solve.
Here's a sample project: https://github.com/dallonf/react-apollo-bug-sync-remount
In a nutshell, a graphql-wrapped component is rendered. On user input, the component is unmounted and replaced by another component that immediately, in componentDidMount, triggers a re-render that causes the graphql component to be re-mounted.
In real-world usage, this type of scenario can be caused by React Router's <Redirect /> component, for example.
The graphql-wrapped component's data.loading prop will be stuck on true, even though the network request has been completed, and the query is correctly updated in the Redux store.
The graphql-wrapped component should behave as it did on its initial mount, where loading will eventually be set to false and its data correctly updated.
The difference between a "stuck" component and a working one seems to be that the APOLLO_QUERY_STOP event triggered when it mounted, which effectively resets the recycled query. I'm not sure exactly why this event is so important, but I do know roughly why it isn't being called.
This event is triggered when you unsubscribe from a query; specifically, the tearDownQuery call in the ObservableQuery.prototype.onSubscribe() method. This only happens when there are _no more observers_ on the query. In this scenario with a synchronous re-mount of a component, there is no point where there are no observers. Here's what happens instead:
graphql starts to recycle the query, calling setOptions, which in turn calls setVariables and result, which ultimately sets up an observer. Let's call it setOptions. There are now 2 observers active.APOLLO_QUERY_STOP should have been called, but there's still an observer active: setOptions_setTimeout, the setOptions observer unsubscribes, too late to save the poor component.I'm not sure what this means. Maybe the fact that this rogue observer unsubscribes on a setTimeout is a bug. Maybe the component shouldn't rely on this APOLLO_QUERY_STOP event to reset the recycled query. Or maybe it ought to explicitly call tearDownQuery() somehow to make sure it's a clean slate. I would have messed around with finding a solution, but I couldn't get the test suite running (reported this separately in https://github.com/apollographql/react-apollo/issues/717), so I had to settle for just reporting the bug.
I have a component that is mounting and unmounted by the router the same as this. I can never seem to keep in a state where it does not be loading constantly. Do you have a fix for this?
Not a fix - that's why I reported the bug. I'm currently working around it by wrapping the component in an HOC that waits a tick before actually rendering it - which is pretty nasty.
I have the same problem, when the same component is unmounted on a route leave and on the next route is mounted again it gets stuck in loading state with networkStatus 2
@dallonf thanks for the reproduction! I'll take a look and see if I can figure out what is happening.
Have the same issue. Within react router, we have a component that we use within different routes, when user navigates from one to another, remounting the component it results with loading: true indefinitely.
+1 I also have the same issue with 100% reproduction rate!
This seems to be also discussed at #667 which has some recent activity regarding to the source of issue and possible solution. Also see #678
This looks like a major issue so I hope there would be a release soon.
good news everyone! This will be fixed in 1.4.0 which should release tomorrow!
Good one James!
Unfortunately this still hasn't resolved the issue for me. Upgraded apollo-client to 1.4.0, I have "react-apollo": "^1.2.0", . The issue, as described, occurs when unmounting / remounting the same component on different routes. Also happens only on first change of the variables, if I go back and forth to this page using browser back button, it renders correctly. I receive the data from server correctly, APOLLO_QUERY_RESULT also updates network status to 7, the same happens in APOLLO_QUERY_RESULT_CLIENT on second try and then it works. Did the new version solve it for anybody else?
@hizo Should we wait for this PR (https://github.com/apollographql/react-apollo/pull/740) to be merged?
hmm looks like it. hopefully it will happen soon
This is now fixed via 1.4.0! You will need to update apollo-client to the same version!
Most helpful comment
good news everyone! This will be fixed in 1.4.0 which should release tomorrow!