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

match workaround for client-side rendering doesn't work with async onEnter hooks #2714

Closed
ngoossens opened this issue Dec 14, 2015 · 15 comments

Comments

@ngoossens
Copy link

Hi

Following the advice of issue #2036 works to correctly render the content on the first pass until you add an async onEnter hook. When this is done the issue returns because again the location ends up being null and a null component is rendered.

This can be reproduced using the following route:

export default {
  path: 'about',
  component: About,
  onEnter: function enter(nextState, replaceState, callback) {
      setTimeout(callback, 1000);
  },
}

I have made a small modification to the example-react-router-server-rendering-lazy-routes illustrating the problem here: https://github.com/ngoossens/example-react-router-server-rendering-lazy-routes

Thanks in advance for any assistance!

@taion
Copy link
Contributor

taion commented Dec 14, 2015

Per https://github.com/rackt/example-react-router-server-rendering-lazy-routes/blob/master/modules/client.js#L12 you need to run match on the client side. See other discussion on issue tracker here.

@taion taion closed this as completed Dec 14, 2015
@ngoossens
Copy link
Author

@taion, the example I posted does that, (see https://github.com/ngoossens/example-react-router-server-rendering-lazy-routes/blob/master/modules/client.js#L12) but the issue still persists.

@taion
Copy link
Contributor

taion commented Dec 14, 2015

I see - the current API setup doesn't let us do much about this. Can you memoize the result of your onEnter hook?

@taion taion reopened this Dec 14, 2015
@ngoossens
Copy link
Author

I could work around this by making sure the request is completed before the initial render is done. Maybe something to consider for future API developments?

@taion
Copy link
Contributor

taion commented Dec 14, 2015

Right, #2036 is a "good-enough-for-most-use-cases" workaround. We'll have something more... eventually.

@ngoossens
Copy link
Author

Thanks.

@levibotelho
Copy link

Running match on the client as suggested in the example referenced above isn't getting rid of the error for me.

Is there any specific development planned to resolve this issue? Do you guys know the root cause? I would be happy to try and lend a hand to fix it if need be...

@ngoossens
Copy link
Author

@levibotelho, the first time render runs this.state.location of the router is null because it is set asynchronously. This means that a null is returned from the render function here: https://github.com/rackt/react-router/blob/master/modules/Router.js#L98

This is hooked up through a history listener here: https://github.com/rackt/react-router/blob/master/modules/Router.js#L66 and here: https://github.com/rackt/react-router/blob/master/modules/useRoutes.js#L234

Pre-running match ensures the files are loaded (webpack, etc) so if there are no asynchronous hooks then when the router mounts it effectively runs match synchronously and has the correct state for the first render.

To work around the problem we would need a way to wait for or inject the correct state into useRoutes which is set up in the routers componentWillMount here: https://github.com/rackt/react-router/blob/master/modules/Router.js#L60

@levibotelho
Copy link

@ngoossens Alright well that explains why match isn't working for me (I have async hooks). Thanks for the info. I'll think about this and if I can figure out some form of solution I'll come back to you and see what you think. This is unfortunate because it worked well in < 1.0.0; would be nice to find a fix!

@taion taion changed the title Renders <noscript> tag for async onEnter hook match workaround for client-side rendering doesn't work with async onEnter hooks Dec 17, 2015
@ryanflorence
Copy link
Member

failing test case would be awesome here

@levibotelho
Copy link

@ryanflorence I'll give the failing test case a shot if there has been no advancement so far on the issue.

Would be good to give this the "bug" tag.

@morlay
Copy link

morlay commented Jan 18, 2016

@taion
Copy link
Contributor

taion commented Jan 18, 2016

Your code is wrong. Follow what's in the tests until we have a chance to update docs. Try Stack Overflow or Reactiflux for support if you're still having problems.

@morlay
Copy link

morlay commented Jan 18, 2016

Seems we should write the client.js like this ?

import React from 'react'
import { match, Router, RouterContext, browserHistory as history } from 'react-router'
import { render } from 'react-dom'
import routes from './routes/RootRoute'

const { pathname, search, hash } = window.location
const location = `${pathname}${search}${hash}`

match({ routes, location }, (error, redirectLocation, renderProps) => {
  render(
    <Router
      {...renderProps}
      history={history}
    />,
    document.getElementById('app')
  );
});

@okendoken
Copy link

@morlay thanks for your example! It worked for me

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

No branches or pull requests

6 participants