React-helmet: Decide where to render scripts on client

Created on 23 Apr 2016  路  4Comments  路  Source: nfl/react-helmet

I'm developing an isomorphic JS app using react-router and react-helmet.
Server-side, I pre-render my app as

const helmet = Helmet.rewind();
`<!DOCTYPE html>
 <html ${helmet.htmlAttributes.toString()}>
      <head>
         <meta charset="utf-8">
         <meta name="viewport" content="width=device-width, initial-scale=1">
         ${helmet.meta.toString()}
         ${helmet.title.toString()}
         ${helmet.base.toString()}
         ${helmet.link.toString()}
     </head>
     <body>
         <main id="react-root">
             ${reactOutput}
         </main>
         ${helmet.script.toString()}
     </body>
 </html>`

reactOutput is the result on rendering on server my route, and it's all handled by react-router.
My top-level components have the following structure

<div>
    <Helmet />
    <NavStuff />
    <PageStuff />
</div>

Thus when I navigate client-side and react-router renders a new route, Helmet creates new <script>s inside <head> because there is no one telling it to put them elsewhere.
This has the undesired effect of reloading my scripts. They are cached so that's not a big deal, but there's no reason to make an HTTP request.
This also happens when changing page a second time, and I'm not really sure why given the script tags are already in the head now.

Any suggestions?

enhancement

Most helpful comment

@mattecapu This may be a worthwhile feature for someone who needs to have an external script outside of React. We can look into Helmet observing where the script tags are rendered and updating them in that location in the DOM. I don't imagine the API changing, just Helmet being smart is knowing where you've prerendered your script tags.

All 4 comments

@mattecapu - Thanks for your interest in Helmet. For your situation, unfortunately it is as-designed. This library is a document head manager and really only deals with managing the head. As you've found, regardless of where you prerender your head attributes, they will always be written and updated in the head on the client-side.

Can the functionality of that external script be handled within React's routing? I'd like to understand your use case.

Hi @cwelch5, thank you for your time.
I could probably handle this manually using react-router's onUpdate hook, but it seems unelegant, that's why I asked here.
What would I need to to that? Should Helmet be rendered to be able to call Helmet.rewind?

@mattecapu This may be a worthwhile feature for someone who needs to have an external script outside of React. We can look into Helmet observing where the script tags are rendered and updating them in that location in the DOM. I don't imagine the API changing, just Helmet being smart is knowing where you've prerendered your script tags.

Closing - This issues is over a year old. If needed, please feel free to file a new issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

michaelBenin picture michaelBenin  路  3Comments

MiguelMachado-dev picture MiguelMachado-dev  路  4Comments

brokentone picture brokentone  路  4Comments

tiagonapoli picture tiagonapoli  路  3Comments

lyquocnam picture lyquocnam  路  3Comments