Comments (6)
Hey @jbachhardie 👋
This is an interesting! Playing around a bit more with your reproduction, I'm actually not sure this is an issue with useSuspenseQuery
as much as it is the way the app is handling the error boundaries. I can actually reproduce the same situation with useQuery
if I throw the error returned from the hook in the component. See my fork of the reproduction to see this behavior.
Digging in, there are a few things I noticed here though:
The route components are never rendered again once the error occurs. While the error message is properly updated in the UI according to the route you're on, the route component functions aren't called again. I added console.log
s to the top of the two route components (App
and OtherPage
) and notice that neither of these are logged after the error occurs, regardless of how many times I switch the page.
This led me to think that the ErrorBoundary
component isn't getting unmounted when you switch between the routes, which means the this.state.fallback
is maintained and the error fallback is shown instead. I can confirm this to be the case. Adding a console.log
inside componentWillUnmount
in the error boundary shows that the component never actually unmounts. This would explain why it seems the two route components are stuck in the same state.
I'm able to fix the issue by adding a key
prop to the Suspense
boundary for the component passed to the Route element
prop and adding a queryKey
option to each useSuspenseQuery
(see below for the technical reasons for this). Adding these two things makes the app work as you'd expect.
I added some comments in my fork for you to follow if you want to see this working as you'd expect.
Feel free to skip this section unless you're interested in some of the behind the scenes technical reason why
queryKey
is needed for this particular reproduction. This may only apply to your situation if you're using the same query across two different route components.
Just a note on why the queryKey
is necessary here. Both of these components are using useSuspenseQuery
with the same query/variables combination. Due to the mechanics of Suspense, we have a cache behind the scenes that ensures we can look up the request again after the component finishes loading. We use a combination of query
and variables
as the cache key in order to look this request back up. While you aren't technically using the same query in two different components that are mounted at the same time (the usual use case for queryKey
), there is a catch to why this is needed in this particular situation.
In order to avoid issues with React.StrictMode
, we remove the cache entry on component unmount asynchronously. We rely on useEffect
for some implementation reasons, and useEffect
runs twice in strict mode. This would mean that without the async cache eviction, we would accidentally remove the suspense cache entry too early. I believe what you're seeing in this particular reproduction is just the timing between the mount of one route component that happens before the cache removal is run, which means the 2nd route component ends up retaining the same cache entry.
Just as an FYI, we have a section on our docs for query call to call this out in case you needed a reference to it 🙂.
I'm not sure there is actually anything for us to do here. Please let me know if I've missed something. Hope this helps!
from apollo-client.
I should have also mentioned, you can use the errorPolicy
option if you need to tweak how errors are handled inside useSuspenseQuery
. The default value is none
which means that errors are thrown to the nearest error boundary. If you prefer the useQuery
style error
property, you can set errorPolicy
to all
. This is technically meant to be used when you want to show partial data alongside your errors, but you can also use it to avoid the throw
.
See the error handling section in our suspense docs for more information on this.
from apollo-client.
Hey, thank you so much for the thorough reply. I went back and made another attempt at reproduction that more closely zoomed in on the issue and directly compared suspense and non-suspense versions. I discovered that in fact useSuspenseQuery
behaves exactly as expected and the same as useQuery
so there's no issue here. The issue I'm seeing in my app and test setup must be specific to the conditions there and not due to useSuspenseQuery
and I just messed up my initial reproduction.
Sorry for the bother but happy to have confirmed this all works as intended and that our approach to error handling with Suspense wasn't misguided.
from apollo-client.
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.
from apollo-client.
No problem at all! Glad to hear everything is working as expected 🙂
from apollo-client.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
For general questions, we recommend using StackOverflow or our discord server.
from apollo-client.
Related Issues (20)
- Skipped Query returns outdated data after cache clearing HOT 7
- Merge function at the type level not working (+ suggested fix) HOT 13
- Unexpected Data Fetching with `useBackgroundQuery`, StrictMode, `fetchPolicy`: `network-only` (or `no-cache`), and state changes HOT 6
- When use the Apollo Client server side rendering, How to share the cache in cluster server (k8s)? ( did we have file cache? or db cache? ) HOT 3
- Feedback for schema-driven testing utilities HOT 1
- Add `subscribeToMore` functionality to `useQueryRefHandlers`, `useBackgroundQuery` HOT 3
- [Docs] Anchor links seem to be stripped HOT 5
- Incomprehensible type mismatch with query generics HOT 4
- Changes to `context` cause refetches in `useQuery` HOT 12
- Add an option in ApolloClient constructor to return a deep copy of query results (or a way to globally transform results after the caching step) HOT 5
- Potentially unintentionally large AoE breaking changing to typescript `MockedResponse` in type 3.9 HOT 5
- clearStore causes a crash when there is an active query HOT 11
- Getting A on the result.data HOT 4
- BatchHTTPLink is not monitoring friendly HOT 6
- Support extensions in useSubscription HOT 4
- React functionality 'useContext' is not available in this environment [Nextjs app] HOT 4
- Subscription doesn't deduplicate HOT 6
- Types `cache.modify` and `writeFragment` lead to TypeScript errors for documented Apollo examples when specifying generic parameter HOT 1
- SOLVED : TypeError: Cannot return null for non-nullable field Subscription: Next.js frontend + FastApi backend HOT 3
- NextJS with "useSuspenseQuery" not passing headers to request HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from apollo-client.