Skip to content
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

Add support of getStaticProps and getServerSideProps #194

Merged
merged 1 commit into from
Mar 31, 2020

Conversation

kirill-konshin
Copy link
Owner

Fix #192 #173

@kirill-konshin
Copy link
Owner Author

@jwkellyiii @jeroenburgers @bsimpson888 @th0th @Poky85 @bjoluc colleagues, since you expressed interest in getStaticProps and getServerSideProps support in next-redux-wrapper could you please take a look at this PR, at least at the readme: https://github.com/kirill-konshin/next-redux-wrapper/blob/static-and-server-props/README.md

I've upgraded the way how components and functions are wrapped, and how initial state is delivered. I am planning to release this soon, so if you have any feedback, please share.

Copy link

@jwkellyiii jwkellyiii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor fixes to the README for clarity

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@kirill-konshin
Copy link
Owner Author

@jwkellyiii great job, thank you for review. All fixed.

Copy link
Contributor

@bjoluc bjoluc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little busy right now, so here are some Readme-only comments from me as well.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@kirill-konshin kirill-konshin force-pushed the static-and-server-props branch 2 times, most recently from ba1a7ce to 1204602 Compare March 27, 2020 18:25
@kirill-konshin
Copy link
Owner Author

@bjoluc thank you for feedback, everything is fixed now.

@jwkellyiii @jeroenburgers @bsimpson888 @th0th @Poky85 @bjoluc let me do some user testing :) do you find new interface comfortable? Does it makes sense to you?

@jwkellyiii
Copy link

It does make sense, on the surface. I am going to pull the branch into a project and get a feel for it.

@kirill-konshin
Copy link
Owner Author

kirill-konshin commented Mar 27, 2020

@jwkellyiii thank you, it will be great. I think for now (if there would be no more suggestions) I'll merge to master and make a canary release.

@bjoluc
Copy link
Contributor

bjoluc commented Mar 27, 2020

Remember last time before the v5 release when there were issues and PRs of people using the new Readme from master with the old package version? Maybe merging this into a canary branch first would reduce confusion.

@bjoluc
Copy link
Contributor

bjoluc commented Mar 27, 2020

Regarding the interface question: While I would really like to hide the complexity from users, I don't really think we can. But we could export a selection of common hydration reducers similar to what redux-persist does with state reconcilers.

@kirill-konshin
Copy link
Owner Author

@bjoluc agree about dev branch.

Yep, I was also thinking about either a reducer or a middleware. Redux persist works a bit differently though, hydration happens only once, whereas in Next.js every time when user opens a page with getStaticProps or getServerSideProps a state from server will be sent to client, so client has to know how to apply it.

It works like this:

  1. Server
    1. Client opens the page
    2. Next.js calls getServerSideProps
    3. Assume it dispatches an action {type: bump} and state becomes {counter: 1}
    4. During server rendering wrapper picks up state and dispatches {type: HYDRATE, payload: {counter: 1}}
    5. Page is rendered on server
    6. Wrapper sends {counter: 1} to client
  2. Client
    1. During client side render wrapper at client side picks up state from server and dispatches {type: HYDRATE, payload: {counter: 1}}
    2. Client dispatches an action {type: bump} and state becomes {counter: 2}
    3. Client navigates away from initial page
    4. Client returns on initial page
  3. Server
    1. Next.js calls getServerSideProps
    2. As stated in step 1.3 it dispatches an action {type: bump} and state becomes {counter: 1} (again, since server has fresh Store every time)
    3. During server rendering wrapper at server side picks up state and dispatches {type: HYDRATE, payload: {counter: 1}}
    4. Page is rendered on server
    5. Wrapper sends {counter: 1} to client
  4. Client
    1. During client side render wrapper at client side picks up state from server and here is client must decide which state is right

@bjoluc
Copy link
Contributor

bjoluc commented Mar 28, 2020

@kirill-konshin Thanks for the example! My bad, I didn't think about reducer implementations in detail. I can't think of any default behavior other than replacing the client-side state entirely, which is a one-liner anyway.

Apart from that, I had a very promising idea: What if we compute a state diff (from the server's initial state) at the end of getServerSideProps and getStaticProps and merge that into the client state via a reducer? That would allow us to update only the server-touched fields of the state by default and leave the rest of the client's state in place. The "merging in what the server touched" approach could be a reasonable default reducer implementation that many users may not need to change!

Obviously, the counter example problem remains. The great thing about the diff approach, however: In combination with a tool like redux-cookies-middleware, the getServerSideProps implementation could decide what parts of the state it would change on the client side, without the need to write a custom rehydration reducer. For instance, it could update the counter only if it has not been touched by the client yet. When it doesn't update the counter, the server would send an empty diff.

@kirill-konshin
Copy link
Owner Author

@bjoluc I'd say, this is a problem for another library ))) state reconciliation may be veeeery tricky. In the doc I ended up just recommending not to update same state tree roots both on client and server. Let server update it's own roots and client can update it's own. Then all server state can be simply merged into existing one.

Same way we can introduce a concept of server-only safe roots which can be blindly updated, but again, this is not the main purpose of this lib, so maybe we can find something already available and integrate it.

@bjoluc
Copy link
Contributor

bjoluc commented Mar 28, 2020

@kirill-konshin I am a little worried that a strict state separation would compromise the isomorphy of redux-connected components. Plus, I don't feel very comfortable with letting users adopt their state hierarchy to start using the new features (arguably, they don't have to if they take the effort of writing a complex custom reducer). But you are definitely right that there is not one solution to rule them all, and helping users with this does not have to be within the scope of this library.

Nevermind, I think you did a great job on the new interface! Users of the new functions will simply have to face the complexity.

Something already available: jsondiffpatch. Users could integrate that themselves if they want to (custom serialization method and hydration reducer).

@bjoluc
Copy link
Contributor

bjoluc commented Mar 28, 2020

@kirill-konshin Another question: What's the motivation behind letting users wrap each page component with a <Provider> themselves? That looks like it could lead to a lot of avoidable boilerplate code...

Copy link
Contributor

@bjoluc bjoluc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, some more little things.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@leighs-hammer
Copy link

@kirill-konshin thank you for all the great work!

This all looks great, I will try spool this up to test tomorrow.

I think the persistence and hydration processes will be relatively simple to leave to other packages or simply baked into apps as a hook that pulls a whitelisted set of keys from session or localstorage when available and hydrate. I already do that for a couple of auth0 ping / pong redirect flows in apps.

Thanks again for all your hard work, and I look forward to this release :)

@kirill-konshin
Copy link
Owner Author

@bjoluc:

@kirill-konshin Another question: What's the motivation behind letting users wrap each page component with a <Provider> themselves? That looks like it could lead to a lot of avoidable boilerplate code...

The reason to make it explicit was 1) to skip dependency on react-redux 2) to make sure users may use Provider the way they want, and 3) to force people to think what they're doing, since App itself was not connected, so I assumed I will extrapolate this model to Pages in this release too.

But you've raised a right question. If App is wrapped then all pages will be connected, for example. So maybe I should wrap everything. No big deal.

@bjoluc:

Something already available: jsondiffpatch. Users could integrate that themselves if they want to (custom serialization method and hydration reducer).

I will add a mention of this lib.

@leighs-hammer:

I think the persistence and hydration processes will be relatively simple to leave to other packages or simply baked into apps

I tend to agree. If there will be demand to change it — I'll change it.

@kirill-konshin
Copy link
Owner Author

@bjoluc Provider wrapping added.

@ferreiradev
Copy link

I didn't want to say anything, but there is a whole team of devs in my company waiting for this new version and thank you very much in advance @kirill-konshin

@kirill-konshin
Copy link
Owner Author

I will make a usable NPM canary release today. Thank you all for feedback.

Add support of getStaticProps and getServerSideProps
@kirill-konshin kirill-konshin changed the base branch from master to dev March 31, 2020 21:40
@kirill-konshin kirill-konshin merged commit 59b798d into dev Mar 31, 2020
@kirill-konshin kirill-konshin deleted the static-and-server-props branch March 31, 2020 21:41
@kirill-konshin
Copy link
Owner Author

Merged to dev. Created a follow up PR to master: #196.

Published https://github.com/kirill-konshin/next-redux-wrapper/releases/tag/6.0.0-rc.1

@jwkellyiii
Copy link

@kirill-konshin it appears that commit 1204602 didn't make it to 6.0.0-rc.1. Any reason why?

@kirill-konshin
Copy link
Owner Author

I messed up Travis config and it published it twice ) second failed obviously

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

new next.js 9.3.0 getServerSideProps is not getting modified context
5 participants