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

Wait to render before promise is resolved. #129

Open
masureshho opened this issue Jun 12, 2018 · 13 comments
Open

Wait to render before promise is resolved. #129

masureshho opened this issue Jun 12, 2018 · 13 comments

Comments

@masureshho
Copy link

masureshho commented Jun 12, 2018

@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.

@finom
Copy link

finom commented Jun 22, 2018

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).

@finom
Copy link

finom commented Jun 22, 2018

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?

@finom
Copy link

finom commented Jun 22, 2018

@aleksxor @AVVS any ideas why that could happen?

@kc-beard
Copy link

kc-beard commented Aug 21, 2018

@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

@finom
Copy link

finom commented Aug 21, 2018

@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.

@kc-beard
Copy link

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.

@ekscentrysytet
Copy link

ekscentrysytet commented Oct 18, 2019

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 ?

@AVVS
Copy link
Member

AVVS commented Oct 18, 2019

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

@ekscentrysytet
Copy link

ekscentrysytet commented Oct 18, 2019

@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

@AVVS
Copy link
Member

AVVS commented Oct 18, 2019

well, make sure that

    return dispatch(auth());

returns a promise. if its not a promise - it wont wait until this is finished

@ekscentrysytet
Copy link

@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

@finom
Copy link

finom commented Aug 10, 2020

Any alternatives to this library?

@ekscentrysytet
Copy link

ekscentrysytet commented Aug 12, 2020

@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

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

No branches or pull requests

5 participants