React-helmet: Using `[email protected]`, `Helmet.rewind()` doesn't give the expected results

Created on 1 Apr 2016  Â·  18Comments  Â·  Source: nfl/react-helmet

In the following snippet, when rendering on the server:

let rendered = ReactDomServer.renderToStaticMarkup(
        <RouterContext {...renderProps} />);
let head = Helmet.rewind();
const html = `
    <!doctype html>
    <html>
        <head ${head.htmlAttributes.toString()}>
            ${head.title.toString()}
            ${head.meta.toString()}
            ${head.link.toString()}
        </head>
        <body>
            <div id="content">
                // React stuff here
            </div>
        </body>
    </html>
`;

the value of html is:

  <!doctype html>
  <html>
      <head >



      </head>
      <body>
          <div id="content">
              // React stuff here
          </div>
      </body>
  </html>

... so basically all the toString()s simply output empty strings.
The rest of the rendering is OK, with all my components rendering as they're
are expected to.

Is there anything wrong with my snippet above?

Most helpful comment

I ran into a similar issue, but @bguiz' guidance led me to the solution. I was importing react-helmet in my app's Webpack build, then importing a separate instance in its server-side code. The fix that worked was to reexport Helmet from the Webpack entrypoint, then import that particular instance into the server code along with the rest of my app. Hope that's useful to anyone else who stumbles across this issue! Thanks for the insight @bguiz.

All 18 comments

I'm also seeing this bug. When the same code renders client side, it works fine. (Although I'm using renderToString)

My guess is that it doesn't support the mew react-router yet
On 6 Apr 2016 21:00, "Myles Eftos" [email protected] wrote:

I'm also seeing this bug. When the same code renders client side, it works
fine.

—
You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
https://github.com/nfl/react-helmet/issues/125#issuecomment-206310474

@bguiz We use RR 2.0.1 + Helmet in-house and we haven't seen any conflicts between the libraries.

+1 I'm having the same issue here : Helmet.rewind is giving me empty fields on server while it's working good on client side !

@doctyper It seems that several of us here are having issues. Just
confirming that you are using it for server rendering as well?

If so, could you please update the react-helmet-example to use
react-router@2 (it's currently using [email protected]):
https://github.com/mattdennewitz/react-helmet-example/blob/master/package.json#L12

... and then I'd like to see what is done differently when rendering
on the server: https://github.com/mattdennewitz/react-helmet-example/blob/master/server.js#L30-L48

CC @mattdennewitz
W: http://bguiz.com

On 7 April 2016 at 18:59, Félix Bayart [email protected] wrote:

+1 I'm having the same issue here : Helmet.rewind is giving me empty fields
on server while it's working good on client side !

—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@bguiz Yes indeed, we are using React Router 2.0.1 + Helmet 3.0.1 in production with server-side-rendering.

There is a working example in our Wildcat example project.

@doctyper That's strange ! My code is really simple but it still doesn't work on server (with no errors)

import routes from '../../assets/src/scripts/routes'
import { renderToString } from 'react-dom/server'
import Helmet from 'react-helmet'
import { match, RouterContext } from 'react-router'
import express from 'express';

export const app = express();
app.get('*',(req, res) => {
    match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
            let content = renderToString(<RouterContext {...renderProps} />);
            let head = Helmet.rewind();
            res.status(200).send(head.title.toString()+head.meta.toString());
    });
});

var PORT = process.env.PORT || 8081;
app.listen(PORT, () => console.log('Running on port ' + PORT));

Any idea on how I could debug that ?

@yukulelix Yeah, I'm getting empty strings rendering in exactly the same way as you, with the only difference being that I'm using renderToStaticMarkup() instead of renderToString(), like so:

let rendered = ReactDomServer.renderToStaticMarkup(
        <RouterContext {...renderProps} />);
helmet = Helmet.rewind();

@doctyper I assume you're referring to this snippet? Thanks for the heads up, I'll try to see if I can spot where I'm stuffing up!

OK, so I've got to the bottom of this issue (at least in my case)... it was that Helmet.rewind() is a static method call, which is totally fine if you only include it in one place as a dependency. If there's more than one, swap it over to peerDependencies - or otherwise ensure that you are using the same instance - and works as expected.

Not sure if the cause is the cause is the same for you, @madpilot and @yukulelix but I'm closing this issue. Ask @doctyper to re-open if this is the case!

W: http://bguiz.com

Thx @bguiz , it works now.
I was compiling my server and client javascript using different environments !
Regrouping them using the multi-compiler feature of Webpack fixed it !
Cheers

@bguiz could you explain this situation? I adeed react-helmet 3.1.0 to peerDependencies to my package.json. Nothing happens unfortunately

@asiniy The root cause of the problem (at least for me) was that there are multiple instances of react-helmet being loaded. Therefore any global static state would have multiple copies, and behave incorrectly. In my case, the solution was to ensure that there was only one copy of react-helmet in my dependency graph, and I achieved this using peer dependencies. The solution in your case may not be the same, but you might have some luck by making sure to remove all but one copy of react-helmet.

I ran into a similar issue, but @bguiz' guidance led me to the solution. I was importing react-helmet in my app's Webpack build, then importing a separate instance in its server-side code. The fix that worked was to reexport Helmet from the Webpack entrypoint, then import that particular instance into the server code along with the rest of my app. Hope that's useful to anyone else who stumbles across this issue! Thanks for the insight @bguiz.

So you're not doing import Helmet from 'react-helmet' in the server? You're doing something like import App, {Helmet} from '../src/containers/App'?

Something like that! My Webpack configuration creates two builds, one for the client and one for the server. The server entrypoint looks like this:

import 'babel-polyfill'

export { A, buildStore } from 'app/flux'
export { App } from 'app/views'
export { flushWebpackRequireWeakIds } from 'react-loadable'
export Helmet from 'react-helmet'

Since _that_ winds up being the instance of Helmet that accumulates state when I render App, that's the one I have to import and call renderStatic() on when I want to get that state back out.

I had exactly the same problem with React router v4 with SSR.

THIS WAS A LIFESAVER!!!

in my ./Application.js which is wrapped by a browser-router for the web and a static router for the server,

did:
export const AppHelmet = Helmet

and used that all over the app and also for where I did AppHelmet.renderStatic()

@phyllisstein @raubas @kenfehling
Thank for your advise.
I found a way to resolve this problem. Use the same node_modules.
Use the client's helmet , it works very well. Below:

import {Helmet} from '../../client/node_modules/react-helmet';

export function index(ctx) {
        const store = configureStore(loginStore);

        renderToStaticMarkup(<Provider store={store}>
          <StaticRouter location={ctx.url} context={{}}>
            <App/>
          </StaticRouter>
        </Provider>);
        const helmet = Helmet.renderStatic();
        console.log('title',helmet.title.toString());
  }
}

I just added this line externals: ["react-helmet"], to webpack server config, It works!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mattecapu picture mattecapu  Â·  4Comments

olalonde picture olalonde  Â·  3Comments

aequasi picture aequasi  Â·  3Comments

bratva picture bratva  Â·  4Comments

joshwcomeau picture joshwcomeau  Â·  3Comments