# react-helmet-async [![CircleCI](https://circleci.com/gh/staylor/react-helmet-async.svg?style=svg)](https://circleci.com/gh/staylor/react-helmet-async) [Announcement post on Times Open blog](https://open.nytimes.com/the-future-of-meta-tag-management-for-modern-react-development-ec26a7dc9183) This package is a fork of [React Helmet](https://github.com/nfl/react-helmet). `` usage is synonymous, but server and client now requires `` to encapsulate state per request. `react-helmet` relies on `react-side-effect`, which is not thread-safe. If you are doing anything asynchronous on the server, you need Helmet to encapsulate data on a per-request basis, this package does just that. ## Usage **New is 1.0.0:** No more default export! `import { Helmet } from 'react-helmet-async'` The main way that this package differs from `react-helmet` is that it requires using a Provider to encapsulate Helmet state for your React tree. If you use libraries like Redux or Apollo, you are already familiar with this paradigm: ```javascript import React from 'react'; import ReactDOM from 'react-dom'; import { Helmet, HelmetProvider } from 'react-helmet-async'; const app = ( Hello World

Hello World

); ReactDOM.hydrate( app, document.getElementById(‘app’) ); ``` On the server, we will no longer use static methods to extract state. `react-side-effect` exposed a `.rewind()` method, which Helmet used when calling `Helmet.renderStatic()`. Instead, we are going to pass a `context` prop to `HelmetProvider`, which will hold our state specific to each request. ```javascript import React from 'react'; import { renderToString } from 'react-dom/server'; import { Helmet, HelmetProvider } from 'react-helmet-async'; const helmetContext = {}; const app = ( Hello World

Hello World

); const html = renderToString(app); const { helmet } = helmetContext; // helmet.title.toString() etc… ``` ## Streams This package only works with streaming if your `` data is output outside of `renderToNodeStream()`. This is possible if your data hydration method already parses your React tree. Example: ```javascript import through from 'through'; import { renderToNodeStream } from 'react-dom/server'; import { getDataFromTree } from 'react-apollo'; import { Helmet, HelmetProvider } from 'react-helmet-async'; import template from 'server/template'; const helmetContext = {}; const app = ( Hello World

Hello World

); await getDataFromTree(app); const [header, footer] = template({ helmet: helmetContext.helmet, }); res.status(200); res.write(header); renderToNodeStream(app) .pipe( through( function write(data) { this.queue(data); }, function end() { this.queue(footer); this.queue(null); } ) ) .pipe(res); ``` ## Usage in Jest While testing in using jest, if there is a need to emulate SSR, the following string is required to have the test behave the way they are expected to. ```javascript import { HelmetProvider } from 'react-helmet-async'; HelmetProvider.canUseDOM = false; ``` ## Prioritizing tags for SEO It is understood that in some cases for SEO, certain tags should appear earlier in the HEAD. Using the `prioritizeSeoTags` flag on any `` component allows the server render of react-helmet-async to expose a method for prioritizing relevant SEO tags. In the component: ```javascript A fancy webpage ``` In your server template: ```javascript ${helmet.title.toString()} ${helmet.priority.toString()} ${helmet.meta.toString()} ${helmet.link.toString()} ${helmet.script.toString()} ... ``` Will result in: ```html A fancy webpage ... ``` A list of prioritized tags and attributes can be found in [constants.js](./src/constants.js). ## Usage without Context You can optionally use `` outside a context by manually creating a stateful `HelmetData` instance, and passing that stateful object to each `` instance: ```js import React from 'react'; import { renderToString } from 'react-dom/server'; import { Helmet, HelmetProvider, HelmetData } from 'react-helmet-async'; const helmetData = new HelmetData({}); const app = ( Hello World

Hello World

); const html = renderToString(app); const { helmet } = helmetData.context; ``` ## License Licensed under the Apache 2.0 License, Copyright © 2018 Scott Taylor