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

Document Redux setup in additional environments like React Native and Next.js and link additional templates #4035

Open
markerikson opened this issue Mar 13, 2021 · 17 comments
Labels

Comments

@markerikson
Copy link
Contributor

markerikson commented Mar 13, 2021

Our docs currently teach app setup based on a standard SPA-style approach, and specifically with use of Create-React-App. Related, our installation instructions currently point to the two RTK templates for CRA (JS and TS).

We should add additional installation and setup instructions for other major React environments, like React Native and Next which both differ significantly in how the app structure is defined and have different considerations (no ReactDOM.render() call in RN or Next, and Next users will likely want to integrate with Next's data fetching APIs).

We could possibly do this by updating/rewriting https://redux.js.org/usage/configuring-your-store to be more about "how do you set up a Redux store in various environments?" and covering RN/Next specifically as part of that, or we could keep the idea of "store configuration" and "app project setup" in separate pages.

Related to this, it would be nice if we could point to specific templates for those environments as well.

For RN, there's https://github.com/rahsheen/react-native-template-redux-typescript , which ports the RTK+TS example to the RN CLI.

For Next, there's https://github.com/vercel/next.js/tree/canary/examples/with-redux , which does something similar.

@rahsheen
Copy link

Just FYI, I should have a JS version of the RN template as well as TS and JS versions for Expo coming soon. Will look into adding these to the docs in a way that doesn't look ridiculous.

@markerikson markerikson changed the title Link or create additional RTK templates Document Redux setup in additional environments like React Native and Next.js Nov 27, 2021
@markerikson markerikson changed the title Document Redux setup in additional environments like React Native and Next.js Document Redux setup in additional environments like React Native and Next.js and link additional templates Nov 27, 2021
@crutchcorn
Copy link
Member

crutchcorn commented Dec 2, 2021

I've worked a bit on the RN docs side of things. I think a PR is ready for that one. I wanted to wait until I added the NextJS section but had some questions on it first.

You mentioned that we probably want to document usage of NextJS's data fetching APIs, but the template linked doesn't seem to use getStaticProps or getServerSideProps. Is this still something we want to look into documenting?

AFAIK, even prior NextJS projects I've worked in before have tended not to utilize these methods in prod

@markerikson
Copy link
Contributor Author

Yeah, that's something that had crossed my mind.

Part of me says that not everyone is going to need to do SSR-type behavior and need next-reducer-wrapper. I've actually got a Next app at work right now, and we're not using that at all.

But, it's also a common enough thing that I can see the point in having the official Redux+Next starter project have that built in to at least show how it should be set up.\

I know that the Next folks are happy to accept PRs to improve those projects, I just don't have time to even think about that work myself.

@crutchcorn
Copy link
Member

You know, I honestly just didn't even know about next-reducer-wrapper until you pointed it out. After looking into it more, it definitely seems like the ecosystem's choice for doing the SSR-hydration with Redux

It even has a NextJS repo example: https://github.com/vercel/next.js/tree/canary/examples/with-redux-wrapper

If we're okay with using the next-reducer-wrapper as the jumping off point for NextJS I think I can draft different smaller sections ("this is how to do it without SSR, this is how to do it with, here's the difference") as part of the parent. I'll see what I can do this weekend

@markerikson
Copy link
Contributor Author

markerikson commented Dec 3, 2021

Sounds good!

It may be worth at least mentioning that RTK 1.7 will have SSR support as well.

@markerikson
Copy link
Contributor Author

I wrote a Reddit comment recently about how Next and Redux fit together:

https://www.reddit.com/r/javascript/comments/rpsyed/migrating_a_mean_angularjs_app_to_react_nextjs/hq6kk44/

Pasting here for ease of reading:

Depends on how you're trying to use Redux, in much the same way that it depends on how you're trying to use React.

If you're only using Next as a client-side tool (ie, like CRA but with multiple pages), then conceptually your Redux usage is similar. Create a store on the client side, dispatch some actions, fetch some data, etc. Where it gets trickier is that A) Next has multiple pages instead of one, and B) even in the CSR-only scenario Next will try to statically generate HTML for each page by default. That means you have to set up the Redux scaffolding so it creates a unique Redux store on demand per page, rather than just once from index.js like you would in a CRA app. I showed an example of the store creation setup code I cobbled together for this use case based on some Next examples.

Another question is whether you're going to have one store for the entire app regardless of what page you're on, or whether you're going to have different stores with different reducers for each page. I started out with separate stores per-page, and then later switched to one store for the entire app containing all reducers regardless of page.

The SSR question is separate. Redux has always been usable for SSR scenarios - even the original README says "works great in isomorphic apps because it doesn't use singletons and the data can be rehydrated". The basic pattern is:

  • Create a Redux store on the server during the request. Fetch some data, do initial React rendering to HTML string.
  • Get the Redux store state and include it in the generated HTML as a global JS variable
  • On the client side, create the store and pass in that serialized state to act as the initial state

The same pattern applies here to Next usage, except that it is again more complicated due to the multi-page setup scenario and Next's different options for fetching data on the server.

That's why there's a fairly complex library called https://github.com/kirill-konshin/next-redux-wrapper , which tries to abstract the process of grabbing data from the server-side APIs and rehydrating that data into the Redux store on the client side.

We actually just added SSR/rehydration support to RTK Query in the recent RTK 1.7 release, and we specifically have instructions and an example of using RTKQ in combination with next-redux-wrapper:

@markerikson
Copy link
Contributor Author

I just wrote up a fairly similar comment and am pasting here for posterity and later documenting:

With CRA, creating the store and adding the <Provider> is easy. There's already an easily visible root.render(<App />) in src/index.js, and you just import the store and wrap that in <Provider store={store}>.

With Next, there is no one single render() call, because A) Next does that internally, and B) there are many pages.

So what you typically have to do is add a pages/_app.js file and wrap that content in <Provider>.

It gets more complicated when you start considering the server-vs-client rendering behavior. Next automatically tries to pre-build pages on the server by default, along with rendering them on the client. That means your code has to handle running on the server, and that includes creating a Redux store for each page.

So, you end up having to write some extra code to manage creating an instance of the store on demand, and having that get used once on the server and again on the client.

THEN, what if you want to use something like getServerSideProps to do some data fetching and feed that into the Redux store on the server for the initial render? You would then want to pass that into the Redux store on the client side to initialize it with the same values used in the server render, but that takes extra work. The standard tool for helping with that is https://github.com/kirill-konshin/next-redux-wrapper , which abstracts the server data lifecycles, helping init the Redux store, and passing along the data from server to client.

@fregayeg
Copy link

fregayeg commented Jul 22, 2022

Hiya! I can take care to add a good RN example but with Expo.

Expo is recommended for beginners/mid-levels based on RN docs and it has a lot of advantages.

👉 This could be motivating to new redux learners + existing developers (like me 😃) .

Also, I know experts in the React Native community who hadn't used Expo before, but today they changed their minds after hearing about Expo team's updates over the past 2 years, especially since the appearance of EAS services

Note: for more information about new Expo's features in recent years visit this link.

👉 I don't know about Next.js and will not be able to do anything on it.

Would you agree with me on working only on adding RN (example + docs) to redux website? 🙏

Just give me the go 💚

thanks

@phryneas
Copy link
Member

@fregayeg honestly though, as redux is a non-native library there shouldn't be any discernible difference between setting it up with vanilla RN or expo, right?

@fregayeg
Copy link

fregayeg commented Jul 23, 2022

@fregayeg honestly though, as redux is a non-native library there shouldn't be any discernible difference between setting it up with vanilla RN or expo, right?

I think yes! We can consider redux in both RN & Expo as third-party acceptable dependency. Maybe the only difference is: When using Expo Go app, debugging with redux devtools could not work properly. But DW I have experienced such case and today I know how to solve this in few simple ways 😉( it'll be obvious to add these information). So do you agree ?

@markerikson
Copy link
Contributor Author

@fregayeg : FWIW, the request in this page isn't actually for a full-blown app :)

What I'm looking for is something sort of along the lines of the existing "Configuring Your Store" page, that would answer questions like:

  • Where does the store live in the folder structure?
  • There's no ReactDOM.render() - where do I add the <Provider> to the component tree?
  • Any other unique aspects of adding Redux to an RN project that would be different from the typical basic CRA/Vite SPA process

@fregayeg
Copy link

fregayeg commented Jul 23, 2022

@fregayeg : FWIW, the request in this page isn't actually for a full-blown app :)

What I'm looking for is something sort of along the lines of the existing "Configuring Your Store" page, that would answer questions like:

  • Where does the store live in the folder structure?
  • There's no ReactDOM.render() - where do I add the <Provider> to the component tree?
  • Any other unique aspects of adding Redux to an RN project that would be different from the typical basic CRA/Vite SPA process

Ok but there is some other interesting topics such:

👉 Some components are only in mobile, and may need a useful state management system such Redux. One of these component is called bottom-sheet.
👉 That's why I'd like to give few examples on these topics as they seem to be interesting and required for RN developers.

@markerikson
Copy link
Contributor Author

Hmm. @fregayeg , I definitely want any differences in Redux DevTools setup covered (if there are any), but I don't think we need to worry about navigation or testing.

@eric-burel
Copy link

My 2 cents regarding Next.js. First my current understanding is that Redux is already SSR friendly, which explains why the Next.js official redux example is pretty straightforward.

In previous versions, you could use getServerSideProps or getStaticProps at page-level to initialize your store with server data and pass it down to the client. You don't strictly need that, but it helps persisting some state, for instance keeping user preferences in memory.

In Next.js 13, each React Server Components is able to call some server code, and you can now do things at page-level. This means you have to handle a tree structure instead of top-level pages. Therefore, you might need a way to instanciate the store once and carry it around. But you don't have usual React context in RSC.
The alternative? The cache function. This kind of usage is not yet documented but I've seen it in the wild and I am preparing a paper on the subject of "server context", soon to be released.
At the time of writing, Next.js 13 beta docs shows how to use cache for data fetching, but you can use it to return a Redux store instead: it will be initialized only once per request.
You can access request specific values via cookies and headers eg to find the current user.

(disclaimer: I don't use Redux and haven't in a while so take all this with a pinch of salt)

@phryneas
Copy link
Member

@eric-burel The Nextjs official redux example that you link there unfortunately does not work for SSR. If you want to use Redux with SSR on Next, you need additional logic that rehydrates the SSR state on the client, and makes sure that each SSR run has a separate Redux store. WIth that official example, all SSR pages would share one store between all users.
=> Redux + NextJs requires the use of https://github.com/kirill-konshin/next-redux-wrapper

We will probably wait what https://github.com/kirill-konshin/next-redux-wrapper brings to the table for Next 13, since it is already impossible to use Redux + Next SSR without that.

@markerikson
Copy link
Contributor Author

@markerikson
Copy link
Contributor Author

WE'VE FINALLY GOT DOCS FOR SETUP WITH NEXT!!!!

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

Successfully merging a pull request may close this issue.

6 participants