-
Notifications
You must be signed in to change notification settings - Fork 787
fix: When doing a SSR with errorPolicy='all', then error should not be lost #2753
Conversation
@mikebm: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Meteor Contributor Agreement here: https://contribute.meteor.com/ |
Lots of noise in the diff from unrelated formatting changes :/ |
This was related to the code not aligning to the prettier config in package.json since I use the prettier plugin. I reverted said noise. |
This Trie class was only ever used to look up sequences of two elements, where the first element was always a DocumentNode and the second element was always a string. PR #2753 by @mikebm highlighted the fact that the Trie was not as easy to reuse as it was originally intended to be. By comparison, a simple Map<DocumentNode, Map<string, QueryInfo>> data structure has better type safety and a clearer purpose, while enabling easier extensions (just add new fields to QueryInfo and update the makeDefaultQueryInfo function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much @mikebm!
Rebased/squashed a bit and added an additional commit that simplifies the RenderPromises
implementation (our fault not yours).
Perfect. I was thinking along the same lines but shied away from my first PR here to be too invasive :). Thank you much for quickly accepting this. |
Many thanks for this fix, folks! |
The error is present during the |
getDataFromTree is already rendering your app to a string. It didn't use to do this in prior versions. It now returns a string which contains your application rendered via renderToStaticMarkup. In your case, rendering it again won't contain the renderPromises Provider which means it will only render it with what is in the Apollo cache, which will not contain your error. You should probably just be using the string result that is emitted from getDataFromTree/getMarkupFromTree. Any reason you aren't and are rendering it a second time? |
Thank you for the explanation, I had no idea. So, does that mean that |
I still use it, it simply just calls getMarkupFromTree. extract won't cache the error for re-hydration because the InMemoryCache won't contain errors, just the cached result. You should be handling the errors on the server in this case. What I do is render a 404 or error component that sets the status code that is handled on the server.
On the server:
Then on the server, you just check context.statusCode and set the http response code accordingly.
|
@mikebm, why doesn't the InMemoryCache contain errors for re-hydration? I'm running into the exact problem @Dattaya mentioned above. I have an Error component that renders specific information about the GraphQL error. The initial SSR shows the error info as expected, but upon client-side hydration, the error information is removed since I'm not sure I understand your solution. In the error case, does the server render static HTML that isn't re-hydrated by the client? Thanks for all your help in this thread 🙏 |
This is just how the Apollo team designed the InMemoryCache in ApolloClient. It only contains cache keys and cache data. In my specific use case, I handle the error during the SSR by using react-router's I use Your use case may be different, but I hope this helps. |
Redirecting is the most elegant solution. So far I save error in import { renderToString } from 'react-dom/server'
import { getMarkupFromTree } from 'react-apollo'
const getDataFromTree = (tree, context = {}) => getMarkupFromTree({ tree, context, renderFunction: renderToString }) |
@mikebm Are there alternatives to |
None that I know of. |
Closes #2680
Closes #2134
Closes #1972
Closes #1781
Closes #615
This change tracks the original observable used during a SSR. When the Query component is recreated due to a Query's promise resolving, then the original queryId used to track the response error is lost. By tracking the original observable, the newly instantiated Query component can reference the original observable to retrieve the actual result. This makes the feature work like the documentation states, which allows server side rendered components to properly handle errors rather than throwing exceptions.