Getting Started
    Core Concepts
    Building Features
    API Reference
    Configuration
    Deployment
    Upgrading
    Migrating
    Pro
    Misc
    Shakacode logoShakaCodeDeveloped by

    Copyright 2026 ShakaCode

    Press Ctrl+K to search anytime
    Burger
    ShakaCode WebsiteCommunityReact on Rails ProGithubSmallView on Github
    Documentation
      Getting Started
      Core Concepts
      Building Features
      API Reference
      Configuration
      Deployment
      Upgrading
      Migrating
      Pro
      Misc
      Shakacode logoShakaCodeDeveloped by

      Copyright 2026 ShakaCode

      Using React Helmet to build <head> content

      Installation and general usage

      See nfl/react-helmet for details on how to use this package. Add this package to your application:

      yarn add react-helmet
      # or: npm install react-helmet
      # or: pnpm add react-helmet

      Example

      Here is what you need to do in order to configure your Rails application to work with ReactHelmet.

      Create a render-function for server rendering like this:

      export default (props, _railsContext) => {
        const componentHtml = renderToString(<App {...props} />);
        const helmet = Helmet.renderStatic();
      
        const renderedHtml = {
          componentHtml,
          title: helmet.title.toString(),
        };
        return { renderedHtml };
      };

      You can add more helmet properties to the result, e.g. meta, base and so on. See https://github.com/nfl/react-helmet#server-usage.

      Use a regular React functional or class component or a render-function for your client-side bundle:

      // React functional component
      export default (props) => <App {...props} />;

      Or a render-function. Note you can't return just the JSX (React element), but you need to return either a React functional or class component.

      // React functional component
      export default (props, railsContext) => (
        () => <App {{railsContext, ...props}} />
      );

      Note, this doesn't work, because this function just returns a React element rather than a React component

      // React functional component
      export default (props, railsContext) => (
        <App {{railsContext, ...props}} />
      );

      Put the ReactHelmet component somewhere in your <App>:

      import { Helmet } from 'react-helmet';
      
      const App = (props) => (
        <div>
          <Helmet>
            <title>Custom page title</title>
          </Helmet>
          ...
        </div>
      );
      
      export default App;

      Register your generators for client and server sides:

      import ReactHelmetApp from '../ReactHelmetClientApp';
      
      ReactOnRails.register({
        ReactHelmetApp,
      });
      // Note the import from the server file.
      import ReactHelmetApp from '../ReactHelmetServerApp';
      
      ReactOnRails.register({
        ReactHelmetApp,
      });

      Now when the react_component_hash helper is called with "ReactHelmetApp" as a first argument it will return a hash instead of an HTML string. Note, there is no need to specify "prerender" as it would not make sense to use react_component_hash without server rendering:

      <% react_helmet_app = react_component_hash("ReactHelmetApp", props: { hello: "world" }, trace: true) %>
      
      <% content_for :title do %>
        <%= react_helmet_app['title'] %>
      <% end %>
      
      <%= react_helmet_app["componentHtml"] %>

      So now we're able to insert received title tag to our application layout:

       <%= yield(:title) if content_for?(:title) %>