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

How to vike-react-redux ? #87

Open
tbscode opened this issue Feb 17, 2024 · 18 comments
Open

How to vike-react-redux ? #87

tbscode opened this issue Feb 17, 2024 · 18 comments

Comments

@tbscode
Copy link

tbscode commented Feb 17, 2024

Hi saw the open pull #57 🚀, I'm very interested in something similar for redux.
But adding a full abstraction over redux seems a little overkill for my case ( & annoying to maintain? )

I'd rather just be able to add a redux provider and global store to renderHtml & renderClient,
whilst using vike-react but without maintaining a seperate plug-in?

Is it already possible to redux with vike-react? ( I didn't manage )

How would one integrate it? ( or does it really require a separate plugin? )

@brillout
Copy link
Member

The general idea here is that vike-react should implement new hooks so that tools like Redux can be integrated in user-land and/or as a Vike extension.

For example, after @yoshi2no implemented vike-redux not only will you be able to use it, but you'll also be able to implement your own custom integration using the hooks that vike-redux uses.

In the meantime, the question is: what do you need from vike-react to be able to integrate Redux?

What you'll most liklely need is to be able to wrap the root component, for that you can see how vike-react-zustand does it. (FYI after vikejs/vike#1283 is implemented we won't need a new Wrapper setting per tool anymore.)

Beyond a Redux wrapper, do you need something else? I guess a way to pass the Redux store from the server to the client-side?

Let me know if that all makes sense. Also, if you're up for it, PR welcome that adds /examples/redux and that accomodates vike-react to make it possible.

@tbscode
Copy link
Author

tbscode commented Feb 17, 2024

Nice I'll bee looking out for vike-redux :D thanks for letting me know.

I'm currently using redux along the lines of official vike redux example

BUT instead of using +onBeforeRenderClient.tsx I use +onRenderHtml.tsx ( & +onRenderClient.tsx ) to inject the initial redux store.

As mofiying +onBeforeRenderclient.tsx causes an additional POST request when navigating clientside slowing down the navigation

You can see this behavior in the official vike redux example checking the netwok tab when navigating. ( Btw should I open this as a seperate issue possibly ? )

I've been able to completely avoid the additional POST /<page>/index.pageContext.json by setting the inital store in +onRenderHtml.tsx instead, see here

If you'd give me a hint on how to achive that whilst using vike-react I'd give it a try.
Current setup works but would be improved / cleaner with vike-react so I can also wait :)

@brillout
Copy link
Member

How about a new hook onAfterRenderHtml()?

@tbscode
Copy link
Author

tbscode commented Feb 17, 2024

Ok interesting yes, this would also prob solve the use case I posted in #community-help on discord.
I.e.: fetching data for the first SSR render, but then not re-fetching / posting to pageContext.json on client navigation.

I would still have to understand how to use this on inject the <Provider> though?

@brillout
Copy link
Member

I'm not sure what you mean, but feel free to suggest something else than creating a new custom hook onAfterRenderHtml().

@tbscode
Copy link
Author

tbscode commented Feb 17, 2024

What eactly would onAfterRenderHtml do?
How would I add the redux <Provider> if the pageHtml is already rendered?

I'd like to:

  1. use redux, wihout modifying +onBeforeRenderClient.tsx ( as this causes the additional POST I'd like to avoid ). In best case use it combined with vike-react.
  2. Fetch data on first Page render ( to initalize the store ), but NOT use +data.ts or +onBeforeRenderClient.tsx as this also causes the additional POST on clientside navigation.

@nitedani
Copy link
Member

nitedani commented Feb 18, 2024

  1. fetch data in +onBeforeRender.tsx, set it on pageContext
  2. add the provider in +Wrapper.tsx, get data from usePageContext

+Wrapper.tsx

const pageContext = usePageContext()
const [store] = useState(() => getStore(pageContext.PRELOADED_STATE))`
...
return <Provider store={store}>...</Provider>

@tbscode
Copy link
Author

tbscode commented Feb 18, 2024

But this would also cause an additional POST request on client side navigation.
Maybe a little example, so I'm working on a chat app:

If the user loads e.g.: /chat I would fetch all the chats for the initial render, use that to initialize the Redux store.
When the user clicks a chat I do client side navigation navigate(...) to /chat/<chat-uuid>, in this case the chats are already loaded into the store, so should NOT be fetched again.

But from my experiments, as soon as I use +onBeforeRender.tsx the navigation /chat -> /chat/<chat-uuid> triggers an additional POST to /chat/chat.pageContext.json. This is make navigating significantly slower.

I think this is just inherently how +onBeforeRender.tsx behaves, so I wonder if there is instead a hook that just runs on the first server side render.

@brillout
Copy link
Member

My thinking was that onAfterRenderHtml() would be called here (i.e. after the HTML is generated but before onRenderHtml() returns). Correct me if I'm wrong but, together with <Wrapper>, I think that would do the trick.

@tbscode
Copy link
Author

tbscode commented Feb 22, 2024

I'm not sure if I understand correctly:

Wrapper is added to pageView in getPageElement, and there I'd initialize the store?

But if onAfterRenderHtml runs after the html is rendered, how can I still inject data to the store?

I could see how it would work with a onBeforeRenderHtml ( also before pageView creation ). So something that runs only of first SSR render but still allows to fetch & pass data for the store initalization.

Since I still think the only way to avoid that vike send a POST /<page>/page.pageContext.json request on client-side navigation ( <page>/some -> <page>/other ) is not to use +onBeforeRender.tsx, in pages/<page>/*.

Correct me if I'm wrong or let me know if I should try to further clarify, thanks for taking the time!

@brillout
Copy link
Member

brillout commented Mar 12, 2024

@tbscode See #96 which is similar to what I meant.

Also see how the other extensions work, e.g. vike-react-query uses <Wrapper>.

Let me know if you still have questions. I can create a PR showcasing what I mean.

@tbscode
Copy link
Author

tbscode commented Mar 19, 2024

Thanks! So afaik +onAfterRenderClient allows me:

✅ client-side page-based fetching +onAfterRenderClient ( lets me simplify the app's client fetching logic, nice! )
❌ server-side fetching + initialize Redux store with dynamic data server-side without +onBeforeRender or +data ( as it causes POST requests on client-side navigation. )

Or is the second case possible in the current vike-react-zustand implementation?

However, I do now have a setup Redux + Vike such that:

  • some store data is initialized ( theme cookies, search & URL params )
  • all pages are rendered server-side (static UI renders immediately)
  • all dynamic data for internal pages is fetched client-side (optional server fetching for public pages)
  • allows full prerender + capacitor native build

I'd still like to migrate to vike-react at some point but don't see any benefits at the moment / I only fear that I might accidentally use some vike stuff that will be deprecated in the future.

So this isn't a high priority for me anymore! I'm happy ;)

I do have some special requirements like injecting URL params into the Redux state and passing some cookies through page context, and I (could) also achieve point 2 sorta by adding some route-based fetch calls to onRenderHtml.

Might be making some wrong assumptions about how vike works?
By the way, a diagram in the docs showing the flow of which +on* hook is hit when (for the SSR scenario) would be really helpful!

@brillout
Copy link
Member

brillout commented May 6, 2024

We've added a new hook onBeforeRenderClient() that may (or may not) help.

Contribution welcome for:

  • Implementing / exploring whether further hooks are needed.
  • Creating a Vike extension vike-react-redux.

a diagram in the docs showing the flow of which +on* hook is hit when

We've added https://vike.dev/hooks#order.

@brillout
Copy link
Member

Updated docs:

@cwagner22
Copy link

I'm trying to follow the docs (https://vike.dev/stores) to setup redux but pageContext.store from onAfterRenderHtml is undefined because it seems that onBeforeRenderHtml is not executed.

@brillout
Copy link
Member

@cwagner22 Indeed it's missing, let me implement it.

@brillout
Copy link
Member

brillout commented Nov 20, 2024

Done & released in 0.5.8.

@brillout
Copy link
Member

@cwagner22 In case your up for it, contribution welcome to create vike-react-redux. Or just publish an example, we'll then create vike-react-redux ourselves.

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

No branches or pull requests

4 participants