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

render called twice on server #76

Closed
jachenry opened this issue Aug 28, 2015 · 5 comments
Closed

render called twice on server #76

jachenry opened this issue Aug 28, 2015 · 5 comments

Comments

@jachenry
Copy link

I've been noticing an issue where the componentWillMount/render methods inside my root component get called twice when rendering on the server. Attached below are some code snippets from the important parts.

Routes.js

    <Route path="/" handler={Main}>
        <DefaultRoute handler={Home} />
        <Route name="signin" path="/signin" handler={Signin}/>
        <Route name="signup" path="/signup" handler={Signup}/>
        <Route name="forgot_password" path="/users/password" handler={ForgotPassword}/>
        <Route name="reset_password" path="/users/password/edit" handler={ResetPassword}/>
        <Route name="account" path="/account/profile" handler={AccountNavigation}>
            <DefaultRoute name="account_profile" handler={AccountProfile} />
            <Route name="account_settings" path="/account/settings" handler={AccountSettings} />
        </Route>
    </Route>

server.js

const location = new ServerLocation({ request, reply });
    Router.create({ location, routes }).run(function(Handler, state) {
        Resolver.resolve(() => <Handler {...state} />).then(({Resolved, data}) => {
            reply(`
                <!DOCTYPE html>
                <html lang="en-us">
                    <head>
                                                ...
                    </head>
                    <body>
                        <div id="react-root">${React.renderToString(<Resolved />)}</div>
                        <script src="${webserver}/dist/client.js" async defer></script>
                    </body>
                </html>
            `);
        }).catch((error) => reply(error.stack).type("text/plain").code(500)); // Just in case!
    });

Main.js

...
    componentWillMount () {
        if (__SERVER__) {
            console.log("Hello server");
        }

        if (__CLIENT__) {
            console.log("Hello client");
        }
    }
...

logs

[1] ==> ✅  Server is listening
[1] ==> 🌎  Go to http://0.0.0.0:8000
[1] onPreResponse
[1] Hello server
[1] Hello server

Is anyone else seeing this issue? The issue goes away when I remove the react-resolver from the equation.

@ericclemmons
Copy link
Owner

That's correct.

Because React doesn't support async rendering, we have to make multiple passes through the component tree until all promises have resolved on the server.

There are a couple ways to try & solve this (#57 for example), but they're all pretty complex and will be resolved at a later date.

@ericclemmons
Copy link
Owner

@bbnnt Mentioned this issue from #77. Is this actually a problem? React is meant to re-render multiple times by design, and this is leveraged to generate a working server-side view.

If it's not, I'd rather close this in favor of #57.

@benbonnet
Copy link

I might lack of a more advanced understanding of react itself right here;
I just liked the fact that for the first page load and when routing, the rendering was occurring after the data fetch. Now the page's empty for a very short amount of time — well, depending on the duration of the fetch
but it still works server side as expected

@ericclemmons
Copy link
Owner

I think @jachenry's question was why rendering happened twice (it can actually happen many more times, depending on the depth of the tree) on the server.

As for the client, by itself, Resolver will render on the client progressively the same way a normal SPA would. There just happens to be a couple ways to:

  1. Wait for the entire tree to resolve before rendering and
  2. Render on the server & render on the client with the pre-resolved data.

Either way, until #57 happens and server-side rendering can pick up mid-tree, the multi-pass approach is the cleanest way of accomplishing this.

Again, it should not be a problem for the application as React intends for the whole tree to be re-renderable at any point in time.

@benbonnet
Copy link

My bad I'm sorry; I should not have pointed this one out on the other post. I was concerned about #75 (links breaks, the solution provided is what I just described right here)

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

3 participants