redux-connect
redux-connect copied to clipboard
Wait to render before promise is resolved.
@asyncConnect does not keep the components render stalled before the promise is resolved. Is this because I am not doing the server-side rendering? P.S I do not want server-side rendering. Does this work only for a client? Please help.
Same issue here. Async connect renders components before returned promise is resolved.
The app is initialized like that:
import { ReduxAsyncConnect } from 'redux-connect';
import { BrowserRouter } from 'react-router-dom';
import ReactDOM from 'react-dom';
import { hot } from 'react-hot-loader';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import 'babel-polyfill';
import routes from './routes';
import store, { history } from './store';
const root = <ReduxAsyncConnect routes={routes} />;
hot(module)(root);
ReactDOM.render((
<Provider store={store}>
<BrowserRouter>
<ConnectedRouter history={history}>
{root}
</ConnectedRouter>
</BrowserRouter>
</Provider>
), window.document.getElementById('react-view'));
I tried to remove ConnectedRouter
and hot(module)
parts but it isn't helped.
The reducer:
import { reducer as reduxAsyncConnect } from 'redux-connect';
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
import reducers from '../redux/reducers';
export default function createReducer() {
return combineReducers({
form: formReducer,
reduxAsyncConnect,
...reducers,
});
}
Store configuration:
const middlewares = [
thunkMiddleware,
sideEffectsMiddleware(),
apiMiddleware(),
routerMiddleware(history),
];
const enhancers = [
applyMiddleware(...middlewares),
window.devToolsExtension && __DEVTOOLS__ ? window.devToolsExtension() : f => f,
];
const store = createStore(
connectRouter(history)(createReducer()),
initialState,
compose(...enhancers),
);
The redux-connect enhancer creation:
const reduxAsyncConnect = asyncConnect([{
key: 'hey',
promise: async ({ store: { dispatch, getState } }) => {
await new Promise(r => setTimeout(r, 5000))
},
}]);
So everything looks set up as described.
There is the part of action log:
[{
"type": "@@router/LOCATION_CHANGE",
"payload": {
"location": {
"pathname": "/login",
"hash": "",
"search": "?redirect=%2F",
"key": "q0k114"
},
"action": "REPLACE"
}
}, {
"type": "@redux-conn/LOAD",
"payload": {
"key": "hey"
}
}, {
"type": "@redux-conn/BEGIN_GLOBAL_LOAD"
}, {
"type": "@redux-conn/BEGIN_GLOBAL_LOAD"
}, {
"type": "@redux-conn/END_GLOBAL_LOAD"
}, {
"type": "@redux-conn/LOAD_SUCCESS",
"payload": {
"key": "hey"
}
}, {
"type": "@redux-conn/END_GLOBAL_LOAD"
},
...
@@router/LOCATION_CHANGE
action call is made inside the enhanced component (via redux-auth-wrapper) but it called before any @redux-conn/XXX
call. If I remove the redux-auth-wrapper enhancer, then another child component is rendered before promise is finalized (so this is not about this library).
Almost everything is looking just fine: actions are fired; store is updated with data returned by promise
function. One problem: all the redux-connect actions are fired with delay, which makes enhanced component render before END_GLOBAL_LOAD
. I noticed that it happens on first route load. If the route is reached second time, children components are rendered normally: after promise is finalized. Any thoughts?
@aleksxor @AVVS any ideas why that could happen?
@finom @masureshho did you find a solution for this? We use server-side rendering on the initial load and redux-connect
properly defers loading, but client-side we aren't seeing the same global loading events being properly fired using asyncConnect
@kc-beard I've written my own super-tricky solution (the company I work for doesn't do open-source, so I can't share code with you, unfortunately). The issue with redux-connect isn't solved so I just removed it from the project.
thanks @finom!
For others who happen to land on this issue, see #116 for related discussion. In short, asyncConnect
won't work for routes that are bundle-split.
I've the same issue as @finom mentioned, i.e. component wrapped with @asyncConnect
is getting rendered before @asyncConnect
promise is resolved on the initial render (i.e. on page reload). However everything works correctly on subsequent transitions.
Packages versions:
"react-redux": "^7.1.1",
"react-router-config": "^5.1.1",
"react-router-dom": "^5.1.2",
"redux-connect": "^10.0.0"
@AVVS @aleksxor guys can you please take a look ?
make sure that you have resolved a list of routes - the module works by walking through the tree of components to be rendered, gathering statics (meaning that a component must be returned as one of . the top-level components from react-router-config
) and then it waits for promises to be resolved. seeing you are using async/await it could be a transpilation issue of sorts
@AVVS We don't do code-splitting yet and I just removed all async/await
usage from my code and it's still fails. Here's the example of my setup:
routes.js
:
[{
component: App,
path: '/',
routes: [
{
path: '/page-path',
component: Page,
},
...
],
...
}]
App.js
const reduxAsyncConnect = asyncConnect([{
promise: ({ store: { dispatch, getState }, route }) => {
console.log('App - asyncConnect');
return dispatch(auth());
}
}]);
const reduxConnect = connect((state, { params }) => {
console.log('App - reduxConnect');
});
export default compose(
reduxAsyncConnect,
reduxConnect,
...
);
Page.js
const reduxAsyncConnect = asyncConnect([{
promise: ({ store: { dispatch, getState }, route }) => {
console.log('Page - asyncConnect');
return dispatch(getPageData());
}
}]);
const reduxConnect = connect((state, { params }) => {
console.log('Page - reduxConnect');
});
export default compose(
reduxAsyncConnect,
reduxConnect,
...
);
When I realod page on /page-path
I see following in console:
App - asyncConnect
App - reduxConnect
Page - reduxConnect
Page - asyncConnect
And when I go to some other page and then navigate back to /page-path
I see following:
App - asyncConnect
App - reduxConnect
Page - asyncConnect
Page - reduxConnect
which is expected - i.e. reduxConnect
should be only triggered after asyncConnect
promise resolved
well, make sure that
return dispatch(auth());
returns a promise. if its not a promise - it wont wait until this is finished
@AVVS yes, it returns a promise. It worth nothing to say that I've faced this problem only after I've upgraded to RR v4 and redux-connect@9
. For RR v3 it was working flawlessly
Any alternatives to this library?
@finom we are really waiting Suspense
for data fetching from React team to go live and RR v6 is already experimental release which features Suspense ready navigation