Declarative, nested, stateful, isomorphic document.title for React

Overview

React Document Title

Provides a declarative way to specify document.title in a single-page app.
This component can be used on server side as well.

Built with React Side Effect.

Installation

npm install --save react-document-title

Dependencies: React >= 0.13.0

Features

  • Does not emit DOM, not even a <noscript>;
  • Like a normal React compoment, can use its parent's props and state;
  • Can be defined in many places throughout the application;
  • Supports arbitrary levels of nesting, so you can define app-wide and page-specific titles;
  • Works just as well with isomorphic apps.

Example

Assuming you use something like react-router:

function App() {
  // Use "My Web App" if no child overrides this
  return (
    <DocumentTitle title='My Web App'>
      <SomeRouter />
    </DocumentTitle>
  );
}

function HomePage() {
  // Use "Home" while this component is mounted
  return (
    <DocumentTitle title='Home'>
      <h1>Home, sweet home.</h1>
    </DocumentTitle>
  );
}

class NewArticlePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = { title: 'Untitled' };
  }

  render() {
    // Update using value from state while this component is mounted
    return (
      <DocumentTitle title={this.state.title}>
        <div>
          <h1>New Article</h1>
          <input
            value={this.state.title}
            onChange={(e) => this.setState({ title: e.target.value })}
          />
        </div>
      </DocumentTitle>
    );
  }
}

Server Usage

If you use it on server, call DocumentTitle.rewind() after rendering components to string to retrieve the title given to the innermost DocumentTitle. You can then embed this title into HTML page template.

Because this component keeps track of mounted instances, you have to make sure to call rewind on server, or you'll get a memory leak.

But What About Meta Tags?

Looking for something more powerful? Check out React Helmet!

Comments
  • Expand support and rename project

    Expand support and rename project

    I've been using react-document-title for an isomorphic project and quickly discovered that most of the pages that are being rendered on the server could use generated metadata such as description and Open Graph.

    I'm proposing renaming the project to react-document-metadata and expand usage to arbitrary props in addition to title:

    <Metadata
      title="My fine page"
      opengraph={{image: this.state.image.url}}
      description={this.getDescription()} />
    

    Naturally only title would be read by the browser for updating window.title but it could also be expanded to support things like dynamic favicons.

    Thoughts?

    opened by simenbrekken 35
  • Race conditions

    Race conditions

    Since 'mountedInstances' is a static property on DocumentTitle it's shared state across all requests. Doesn't this cause race conditions? I'm not sure I totally get how it works yet (i'm new to nodejs and react too).

    opened by qamil 21
  • Node compatibility (fixes #1)

    Node compatibility (fixes #1)

    I've taken the liberty to add a couple of tests to make sure the component behaves as it should.

    You were right about the life cycle implications of componentDidMount, apparently componentDidMount bubbles up while componentWillMount trickles down. I'm guessing this is because componentDidMount expects the component's children to be fully initialized and this is the only way to accomplish that.

    Instead I've just added a simple typeof check to bail out when document is not defined. As this is a global variable, typeof is the only way to determine its existence without causing a reference error.

    I wasn't able to reproduce the issue with addons.Children.only, so I've not touched that code.

    I've also added a lint script so you can run jshint with npm run lint without having to install it globally.

    Emulating a browser via the global module is probably not the most reliable way to test the browser behaviour, but adding a browser test runner as dependency seems overkill.

    opened by pluma 16
  • Check if title should be updated

    Check if title should be updated

    This change prevents the document.title of being updated regardless if it had changed or not.

    When using DocumentTitle today, any time some child component updates, the current document.title updates as well, and it shouldn't.

    opened by buzinas 13
  • Node compatibility

    Node compatibility

    According to React's component reference, componentWillMount will also be run on the server. This means bad things will happen (namely, it will attempt to access document on the server, which likely throws an exception).

    ~~I don't see any reason not to use componentDidMount instead.~~

    EDIT: See PR #2 for why we can't use componentDidMount for this component.

    opened by pluma 9
  • Want to use this module in server, and want to ask

    Want to use this module in server, and want to ask

    according to this line https://github.com/gaearon/react-document-title/blob/master/index.js#L6

    It seems to me that the _serverTitle is singleton for whole server. isn't it?

    opened by ericfong 7
  • Use packages to prevent React v15.5.0 and up from complaining about deprecated API's

    Use packages to prevent React v15.5.0 and up from complaining about deprecated API's

    To prevent React>=15.5.0 from throwing warnings we can't use React.createClass or React.PropTypes directly. For both there are now separate packages on npm. In case of createClass the recommendation is to convert to a ES6 class, however that's a bit more of an involved change. Instead, I reckon we can get this version out and silence those warnings first and then tackle a conversion to ES6 class separately.

    Note: linter and all tests pass, but a warning is thrown by React during tests about calling a used PropType directly. However, I can't seem to figure out why, so it's probably caused by react-side-effect?

    opened by JaapRood 4
  • As high order component

    As high order component

    Initial idea:

    @title(props => `${props.user.name}'s page`)
    class SomeComponent extends Component {
    }
    

    Has its downsides. One obvious example:

    // works
    class SomeComponent extends Component {
      render() {
        return (
          <DocumentTitle title={`{this.state.user}'s profile`}>
            ..
          </DocumentTitle>
        );
      }
    }
    
    // won't work in the proposed api
    @title(...)
    class SomeComponent extends Component {
      render() {
        return (
          ..
        );
      }
    }
    

    But this doesn't happen very happen often, and I don't think it should. See Smart and Dumb Components.

    Would send a PR if this is okay.


    Awesome work by the way, @gaearon!

    opened by srph 4
  • How to get started?

    How to get started?

    Sorry for the newbie question, but I'm having trouble getting this running.

    I've run npm install --save react-document-title

    Then I tried require('../../node_modules/react-document-title/index.js') from my main.js file, then use webpack or browserify to create a bundle.js and link that in instead of the main.js file, but it says Uncaught ReferenceError: DocumentTitle is not defined in my JSX file.

    I see that the bundle is loaded in the browser, and I can see the react-document-title code in the bundle, but it's not available to my JSX for some reason. It's probably a rookie mistake, but I'm stumped. Hope you can give any pointers.

    Cheers

    Example source code:

    index.html

        <script src="https://fb.me/react-with-addons-0.13.3.js"></script>
        <script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/0.13.3/ReactRouter.min.js"></script>
        <script src="~/src/js/bundle.js"></script>
        <script type="text/jsx" src="~/Content/lib/jsx/main.jsx"></script>
    

    main.js

    'use strict'
    
    var DocumentTitle = require('../../node_modules/react-document-title/index.js');
    

    main.jsx

    var Router = ReactRouter;
    var DefaultRoute = Router.DefaultRoute;
    var Link = Router.Link;
    var Route = Router.Route;
    var RouteHandler = Router.RouteHandler;
    
    var App = React.createClass({
        render: function() {
            return (
                <DocumentTitle title='Home'>
                    <this.props.activeRouteHandler />
                    <div id="wrapper">
                    </div>
                </DocumentTitle>
            );
        }
    });
    
    opened by angularsen 4
  • emitting '<noscript></noscript>' to DOM

    emitting '' to DOM

    React = require('react'),
    DocumentTitle = require('react-document-title');
    var Component = React.createClass({
          render: function () {
            return React.createElement(DocumentTitle, {title: 'irrelevant'} );
          }
    });
    
    var markup = React.renderToStaticMarkup(React.createElement(Component));
    

    this is a slightly modified logic of https://github.com/gaearon/react-document-title/blob/master/test/common.js#L9.

    it is emitting '' as its markup.

    I assume it is a bug since we are claiming in README.md that it doesn't emit anything to DOM

    opened by goldensunliu 3
  • Allow 0.13 beta

    Allow 0.13 beta

    I think this works, with inspiration from Omniscient: https://github.com/omniscientjs/omniscient/blob/b6ab57f7fa64886370b2a8ef5e64ff91eac30ad2/package.json

    opened by natew 3
  • When I use it.Why components has been an empty object at this.props?

    When I use it.Why components has been an empty object at this.props?

    May be can't use it like this?

    <Route path="/path"
         render={() => (
          <DocumentTitle title="title">
                  <Component/>
          </DocumentTitle>
     )} />
    
    opened by lujdong 0
  • Issues with importing when using TypeScript

    Issues with importing when using TypeScript

    Using TypeScript and @types/react-document-title.

    I'm trying to do import * as DocumentTitle from 'react-document-title'; but in my render() I get [ts] JSX element type 'DocumentTitle' does not have any construct or call signatures.

    I tried import DocumentTitle from 'react-document-title'; and the page won't load properly.

    export class Test extends React.Component<{}, {}> {
      render() {
        return (
          <DocumentTitle title="Hey">
            Test
          </DocumentTitle>
        );
      }
    }
    
    opened by julianguyen 3
  • Only set prop types in non-production builds.

    Only set prop types in non-production builds.

    This will enable a bundler to omit the prop-types import. I don't think any tool is set up to actually do this (recognize the import is unused and eliminate it before bundling) but it'll save a few bytes either way.

    opened by realityking 0
  • DocumentTitle is undefined when running tests

    DocumentTitle is undefined when running tests

    When using this library with TypeScript, I am encountering errors when running tests:

    import DocumentTitle from 'react-document-title';
    
    // ...
    
    renderToString(
                        <DocumentTitle title="Hello World">
                            <AppComponen/>
                        </DocumentTitle>
    );
    

    My typings file:

    // @types/react-document-title.d.ts
    
    declare module 'react-document-title' {
        import * as React from 'react';
    
        interface DocumentTitleProps {
            title: string;
        }
    
        export default class DocumentTitle extends React.Component<DocumentTitleProps, any> {
            public static rewind(): string;
            public static peek(): string;
        }
    }
    
    

    This code runs perfectly fine when executed on the server, but during testing it fails:

    Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

    Debugging shows that the import of react-document-title simply returns undefined when using jest, but the proper class when running the server.

    Does anybody know what might be the cause of this?

    opened by Birne94 5
  • Readme file Reservations

    Readme file Reservations

    I'm a bit confused by Readme of this library.

    Can be defined in many places throughout the application

    I'm surprised because though the document title can change many times, at any given time there is only one title. Isn't using DocumentTitle component in various places throught the application, splitting the logic of the aplication?

    opened by carpben 0
Releases(v2.0.3)
Owner
Dan Abramov
Working on @reactjs. Co-author of Redux and Create React App. Building tools for humans.
Dan Abramov
A React component to view a PDF document

React PDF viewer A React component to view a PDF document. It's written in TypeScript, and powered by React hooks completely. // Core viewer import {

React PDF Viewer 1.4k Jan 9, 2023
A document head manager for React

React Helmet This reusable React component will manage all of your changes to the document head. Helmet takes plain HTML tags and outputs plain HTML t

National Football League 16.7k Jan 7, 2023
🎯 React component for transportation of modals, lightboxes, loading bars... to document.body or else.

React-portal Struggling with modals, lightboxes or loading bars in React? React-portal creates a new top-level React tree and injects its children int

Vojtech Miksu 2.1k Jan 3, 2023
Complete token authentication system for react + redux that supports isomorphic rendering.

Simple, secure authentication for react + redux TL;DR - View the Live Demo You can see a complete working example here. The code for the demo is here.

Lynn Dylan Hurley 2.1k Dec 27, 2022
Isomorphic application written in React

Isomorphic "Quiz Wall" for itsquiz.com Motivation There are a lot of tutorials and boilerplates showing how to write isomorphic ReactJs applications.

WebbyLab 521 Nov 1, 2022
Appends a new DOM node to the end of the `document.body` and renders it's child React tree into it.

@react-lit/portal Appends a new DOM node to the end of the document.body and renders it's child React tree into it. Useful to break out of the DOM hie

Joel Voss 1 Dec 9, 2021
Document Management System API Backend

Document Management System View on Pivotal Tracker The system manages documents, users and roles. Each document defines access rights i.e. which roles

Kevin Gathuku 9 Oct 1, 2021
Simple declarative and universal A/B testing component for React.

react-ab Simple declarative and universal A/B testing component for React. Demo Install npm install react-ab --save or bower install react-ab --save E

Ola 433 Nov 13, 2022
:tada: React Universal Hooks : just use****** everywhere (Functional or Class Component). Support React DevTools!

react-universal-hooks React Universal Hooks : just use****** everywhere. Support React >= 16.8.0 Installation Using npm: $ npm install --save react-un

Salvatore Ravidà 177 Oct 10, 2022
React ESI: Blazing-fast Server-Side Rendering for React and Next.js

React ESI: Blazing-fast Server-Side Rendering for React and Next.js React ESI is a super powerful cache library for vanilla React and Next.js applicat

Kévin Dunglas 632 Dec 29, 2022
30 Days of React challenge is a step by step guide to learn React in 30 days

30 Days of React challenge is a step by step guide to learn React in 30 days. It requires HTML, CSS, and JavaScript knowledge. You should be comfortable with JavaScript before you start to React. If you are not comfortable with JavaScript check out 30DaysOfJavaScript. This is a continuation of 30 Days Of JS. This challenge may take up to 100 days, follow your own pace.

Asabeneh 18.4k Jan 5, 2023
React Navigation for React js that tries to ensure that the elements of the navigators display correctly on devices with notches and UI elements which may overlap the app content.

React Navigation for React js that tries to ensure that the elements of the navigators display correctly on devices with notches (e.g. iPhone X) and UI elements which may overlap the app content.

MohammadAli Karimi 11 Nov 27, 2022
React People lists and connects React developers around the world.

React People React People lists and connects React developers around the world. Progress View the Project page for details on what's planned and what'

Vitor Leonel 15 Aug 23, 2022
React Backbone Binding that works with React 16

WithBackbone React Higher Order Component which will bind Backbone Data that works with React Fiber (v.16) Why did we make it There are already a coup

Beanworks 2 Mar 19, 2021
A description of React's new core algorithm, React Fiber

React Fiber Architecture Introduction React Fiber is an ongoing reimplementation of React's core algorithm. It is the culmination of over two years of

Andrew Clark 9.8k Jan 5, 2023
React Clone - How React Works: An In-Depth Guide

Как работает React: подробное руководство Привет, друзья! В этой статье я покажу вам, с чего начинается React. Что это означает? Это означает, что мы

Igor Agapov 5 Nov 25, 2021
A drum machine built with React using the Create React App toolchain.

drum-machine A simple drum machine built with React using the Create React App toolchain. Getting Started Clone or download the repository. Open a com

Ryan Schafer 1 Dec 30, 2021
React-Login-app - Create a Login and Registration Page with React Router

About In this repo I was given a Task to create a Login and Registration page wh

Devanshu Desai 3 Dec 10, 2022
Insomnia-react-app - A react app that will help you relax and sleep better

insomnia - a sleep inducer app An app that will help you relax and sleep better.

null 8 Dec 27, 2022