-
-
Notifications
You must be signed in to change notification settings - Fork 265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove double hydration #499
Closed
voinik
wants to merge
1
commit into
kirill-konshin:async-hydration-fix
from
voinik:improve-hybrid-hydration
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Both are needed, because
_app
may havegetInitialProps
and page may havegetServerSideProps
. This have to result in 2 hydrates.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.
One should be sufficient.
In the callback of
wrapper.getInitialAppProps
you dispatch a number actions filling your store.After that inside
wrapper.getServerSideProps
you can dispatch a next set of actions, you can even use the store.getState() together with some selectors to base logic on for further dispatches. These will all get picked up by the store instance and be reduced after thegetInitialAppProps
resulting reduces.After all of this (getInitialProps and sequentially getServerSideProps) in your _app.tsx JSX you call
wrapper.useWrappedStore
which will perform the hydration. At this point yourpageProps.initialState
will also have theinitialState
(if not altered by the GSSP dispatches), it's basically includes both.If you don't render a GSSP page, you will fallback to the initialState from _app.tsx'
getInitialProps
You can check and see all demo app packages still work as expected with this change.
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.
I dug around trying to figure out exactly what the data flow is so here are my findings, which corroborate @karaoak's comment. I wrote this as detailed as I did mostly for myself so that I have a reference to fall back on, but hopefully it explains the idea well!
The data flow roughly goes like this:
pageProps
key, and in our case ainitialState
key, and some other Next.js stuff.Let's say we refresh the page. And let's say we have 2 slices in our store state, one "page" slice for our page, one "generic" slice that gets set on each page through GIP.
We see the generic slice is set now, and the page slice isn't yet, because GSSP hasn't run yet. We also have the initial props now.
We see the generic slice is still set, and the page slice has now also been set, because both GIP and GSSP have run. We also have the page props.
So "pageProps" now contains the page props, and the store state that contains all the dispatches. We don't need the "initialState" version that's outside of "pageProps", we need the one inside of "pageProps" (so
pageProps.initialState
).Now if we don't have GSSP or getStaticProps (GSP) for a page, then it's another story. In that case no extra data is merged into the GIP data, so "pageProps" will not contain an "initialState" key. In this case we do need the "initialState" key that's outside of "pageProps".
So this means that if
pageProps.initialState
exists, we want that store state. If it doesn't exist, then we want theinitialProps
store state. And if that doesn't exist we should usenull
.In your code you assign
pageProps.initialState
to a variable calledinitialStateFromGSPorGSSR
and the "initialState" outside "pageProps" is simply calledinitialState
in your code.So @karaoak's
useHybridHydrate(store, initialStateFromGSPorGSSR ?? initialState ?? null);
line is in fact correct.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.
Very well done!