next-redux-wrapper: next-redux-wrapper usage slows down route change
Describe the bug
Whenever I use next-redux-wrapper, changing routes starts to get really slow.
export const getServerSideProps: GetServerSideProps<I18nProps<MyLocale>> = getStore((store) => async (ctx) => {
// ...
store.dispatch(setFeatureFlags(flags));
// ...
store.dispatch(updateDevice(getSelectorsByUserAgent(ctx.req.headers["user-agent"])));
return ...;
});
With the code above, whenever I change routes, it takes around 10s to change on dev and 5s on prod. If I remove it, it becomes instant, like milliseconds.
To Reproduce
The code is proprietary, I can’t fork or clone it.
Steps to reproduce the behavior:
Just use this library with some dependencies like usedapp, or theming, or any UI lib. Check how long it takes to change routes. Remove it, and you’ll see the difference.
Expected behavior
Using redux shouldn’t impact the app routing load time.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 6]
Additional context
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 2
- Comments: 17 (3 by maintainers)
hi , i had this problem too, you can use 8.0.0-rc.1 instead of 7.0.5 there is some changes
for create store you must use configureStore
and in _app.js:
I can release it, it’s been in beta for quite some time.
I’ve encountered this issue as well, and in my case it’s because, on client-side navigation with
next/linkandnext/router, identicalHYDRATEactions are repeatedly dispatched - 700ish times per navigation for me in dev mode. I think it puts the app into a spinlock until some async task finishes - something, somewhere (possibly not innext-redux-wrapper) is not waiting when it should. I have not found the root cause.Using React 18.2, Next 12.1.6,
next-redux-wrapper7.0.5. Other possibly relevant libraries are RTK Query with@reduxjs/toolkit1.8.2 andconnected-next-router4.1.1 - calling them out because they both do interesting things on route change.Here’s what I found out and a workaround that seems to work for my case, in case they’re useful to you @kirill-konshin or anyone else having this problem. I am using App-level
getInitialPropsonly.It’s coming from
withRedux.shouldComponentUpdate:nextProps.initialStateandthis.props.initialStateare different repeatedly, sothis.hydrateis called repeatedly.I think what’s supposed to happen is:
HYDRATEis dispatched, the store is updated,this.propshas the updated store, that makesthis.props === nextProps, and we move on. But something happens in that process and React tries to re-render before the store is updated, so WrappedApp’s props aren’t updated yet, so it dispatchesHYDRATEagain. Repeat until… this is where I got stuck.I overrode
WrappedApp.prototype.shouldComponentUpdatewith an identical body, with thethis.hydratecall in a timeout. 0 timeout was the same, but waiting 10-50ms reduced the number of dispatches and waiting 100-150ms eliminated the duplicate dispatches. (This is why I wonder if RTK Query is involved - 50-100ms is on the network request timeframe.)In my use case (but not necessarily others!), changing route always changes the Next page. So if we’ve already dispatched a
HYDRATEforthis.props.Component, we know the store is updated. So my workaround is to remember the last page component we hydrated for, and only hydrate if it’s different from this page component:My app doesn’t use page-level
getInitialPropsorgetServerSideProps, it doesn’t look like this would break those but I haven’t tested that case. It might break if you render the same page on different routes though!That RC is pretty good. Thank you @roshaninet