React-helmet: Cant render stringified meta tags on server

Created on 7 Aug 2015  路  4Comments  路  Source: nfl/react-helmet

Helmet.rewind() returns a collection of meta tags as strings.

In my isomorphic/universal app, I have an HTML component that I render on the server:

render() {
  return (
    <html>
      <head>
        {this.props.head.meta}
        <link rel='some existing tags" />
      </head>
      ...
    </html>
  )
}

I render this component to a string React.renderToStaticMarkup(htmlComp);

In this case this.props.head.meta is the string of meta tags i get back from the rewind.

Printing raw strings like this in React wont work of course, it gets escaped. I can't use dangerouslySetInnerHtml on the <head> because it will clobber my existing tags such as the <link>.

The README doesn't explain this very clearly.

What's the intended implementation of the server rendering?

enhancement

Most helpful comment

I ran into the same issue. Here's how I resolved it:

Add a method to your <html> component:

_helmetToComponent(str) {

    // stop if str is empty
    if (!str.length) {
        return;
    }

    // an array of React components
    let Components = [];

    // react-helmet returns a line-break delimited list of tags
    // split so we can deal with each individually
    str.split(/\n/).forEach((node, i) => {

        // extrapolate node type
        let nodeType = str.match(/[a-z]+/)[0];

        // container for props
        let props = {
            key: i
        };

        // match attr="value" pattern
        // store props
        node.match(/([a-z\-]+=".*?")/g).forEach((attr) => {
            let matches = attr.match(/([a-z\-]+)="(.*?)"/);
            props[matches[1]] = matches[2];
        });

        // create and save the component
        Components.push(React.createElement(nodeType, props));

    });

    // return the array of components
    return Components;

}

Call it in your render():

render() {

    let meta = this._helmetToComponent(this.props.head.meta);
    let link = this._helmetToComponent(this.props.head.link);

    return (
        <html lang="en">
            <head>
                <title>{this.props.head.title}</title>
                {meta}
                {link}
            </head>
            ...
        </html>
    );
}

All 4 comments

I ran into the same issue. Here's how I resolved it:

Add a method to your <html> component:

_helmetToComponent(str) {

    // stop if str is empty
    if (!str.length) {
        return;
    }

    // an array of React components
    let Components = [];

    // react-helmet returns a line-break delimited list of tags
    // split so we can deal with each individually
    str.split(/\n/).forEach((node, i) => {

        // extrapolate node type
        let nodeType = str.match(/[a-z]+/)[0];

        // container for props
        let props = {
            key: i
        };

        // match attr="value" pattern
        // store props
        node.match(/([a-z\-]+=".*?")/g).forEach((attr) => {
            let matches = attr.match(/([a-z\-]+)="(.*?)"/);
            props[matches[1]] = matches[2];
        });

        // create and save the component
        Components.push(React.createElement(nodeType, props));

    });

    // return the array of components
    return Components;

}

Call it in your render():

render() {

    let meta = this._helmetToComponent(this.props.head.meta);
    let link = this._helmetToComponent(this.props.head.link);

    return (
        <html lang="en">
            <head>
                <title>{this.props.head.title}</title>
                {meta}
                {link}
            </head>
            ...
        </html>
    );
}

We are looking into expanding the API to allow returning of static markup. We will also expand on the README if necessary.

@bradbarrow @LukeAskew couldn't we just just do a string replace of the rendered markup

// replace the helmet meta tag because react-helmet does not support rendering the meta tags
html = html.replace("<helmetmeta></helmetmeta>", head.meta);

We know offer the ability to use React components or strings, when calling rewind on the server. Check out just released 2.1.0.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tiagonapoli picture tiagonapoli  路  3Comments

kombucha picture kombucha  路  3Comments

jineshmehta16 picture jineshmehta16  路  3Comments

aravind12345 picture aravind12345  路  5Comments

olalonde picture olalonde  路  3Comments