React Native Helmet Async
react-native-helmet-async is a specialized fork of `react-helmet-async`, which itself is a modern, thread-safe solution for managing meta tags in React applications. This particular package addresses the specific needs of React Native by removing the `react-dom` peer dependency, making it suitable for environments where DOM rendering is not present. Its core differentiator is the use of a `<HelmetProvider>` component to encapsulate Helmet state on a per-request or per-tree basis, crucial for asynchronous server-side rendering (SSR) to prevent state pollution across requests. It is currently at version 2.0.4 and appears to be actively maintained, providing an essential tool for SEO and head management in React Native web applications (when used with a web renderer) and isomorphic React projects where `react-dom` is not desired. It solves the thread-safety issues inherent in the original `react-helmet`'s `react-side-effect` dependency.
Common errors
-
TypeError: Cannot destructure property 'Helmet' of 'react-native-helmet-async' as it is undefined.
cause Attempting to import `Helmet` as a default import when it's a named export.fixChange `import Helmet from 'react-native-helmet-async';` to `import { Helmet } from 'react-native-helmet-async';` -
Error: Invariant Violation: Hooks can only be called inside the body of a function component. (e.g., when calling `useContext` outside of a functional component or `Helmet` outside of a provider)
cause Rendering `<Helmet>` or related components without a parent `<HelmetProvider>`.fixWrap your application or the specific components using `Helmet` with `<HelmetProvider>`. -
TypeError: helmet.title is undefined (or similar for meta, link, etc.) in SSR context
cause Forgetting to pass a `context` object to `HelmetProvider` during server-side rendering, or not extracting the `helmet` object from that context.fixEnsure `const helmetContext = {};` is defined and passed as `<HelmetProvider context={helmetContext}>`. After rendering, access properties via `helmetContext.helmet.title.toString()` etc.
Warnings
- breaking The default export for `Helmet` was removed in version 1.0.0. You must now use named imports.
- breaking Introduced the mandatory `HelmetProvider` component to encapsulate Helmet state. All Helmet components must be rendered within a `HelmetProvider`.
- breaking Server-side rendering no longer uses static `rewind()` or `renderStatic()` methods. State is now extracted via the `context` prop passed to `HelmetProvider`.
- gotcha This package is a fork specifically for React Native environments and removes the `react-dom` peer dependency. Using it in a standard web-only React project with `react-dom` might indicate you should be using `react-helmet-async` instead.
- gotcha When running Jest tests that emulate SSR, `HelmetProvider.canUseDOM` must be explicitly set to `false` to prevent DOM-dependent behavior.
Install
-
npm install react-native-helmet-async -
yarn add react-native-helmet-async -
pnpm add react-native-helmet-async
Imports
- Helmet
import Helmet from 'react-native-helmet-async';
import { Helmet } from 'react-native-helmet-async'; - HelmetProvider
const { HelmetProvider } = require('react-native-helmet-async');import { HelmetProvider } from 'react-native-helmet-async'; - HelmetProvider.canUseDOM
import { HelmetProvider } from 'react-native-helmet-async'; // Then forget to set canUseDOMHelmetProvider.canUseDOM = false;
Quickstart
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Helmet, HelmetProvider } from 'react-native-helmet-async';
const App = () => (
<div>
<Helmet>
<title>My Awesome React Native Web App</title>
<link rel="canonical" href="https://www.example.com/" />
<meta name="description" content="A test application for react-native-helmet-async" />
</Helmet>
<h1>Welcome to the App!</h1>
<p>Check the document head for the meta tags.</p>
</div>
);
const container = document.getElementById('root');
if (container) {
const root = createRoot(container);
root.render(
<HelmetProvider>
<App />
</HelmetProvider>
);
} else {
console.error('Root element not found. Please ensure an element with id "root" exists.');
}