How do I keep document.title updated in React app? How do I keep document.title updated in React app? reactjs reactjs

How do I keep document.title updated in React app?


I wrote react-document-title just for that.

It provides a declarative way to specify document.title in a single-page app.
If you want to get title on server after rendering components to string, call DocumentTitle.rewind().

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 on client and server.

Example

Assuming you use something like react-router:

var App = React.createClass({  render: function () {    // Use "My Web App" if no child overrides this    return (      <DocumentTitle title='My Web App'>        <this.props.activeRouteHandler />      </DocumentTitle>    );  }});var HomePage = React.createClass({  render: function () {    // Use "Home" while this component is mounted    return (      <DocumentTitle title='Home'>        <h1>Home, sweet home.</h1>      </DocumentTitle>    );  }});var NewArticlePage = React.createClass({  mixins: [LinkStateMixin],  render: function () {    // Update using value from state while this component is mounted    return (      <DocumentTitle title={this.state.title || 'Untitled'}>        <div>          <h1>New Article</h1>          <input valueLink={this.linkState('title')} />        </div>      </DocumentTitle>    );  }});

Source

I keep track of mounted instances and only use title given to the top DocumentTitle in the mounted instance stack whenever it updates, gets mounted or unmounted. On server, componentWillMount fires but we won't get didMount or willUnmount, so we introduce DocumentTitle.rewind() that returns a string and destroys state to prepare for next request.

var DocumentTitle = React.createClass({  propTypes: {    title: PropTypes.string  },  statics: {    mountedInstances: [],    rewind: function () {      var activeInstance = DocumentTitle.getActiveInstance();      DocumentTitle.mountedInstances.splice(0);      if (activeInstance) {        return activeInstance.props.title;      }    },    getActiveInstance: function () {      var length = DocumentTitle.mountedInstances.length;      if (length > 0) {        return DocumentTitle.mountedInstances[length - 1];      }    },    updateDocumentTitle: function () {      if (typeof document === 'undefined') {        return;      }      var activeInstance = DocumentTitle.getActiveInstance();      if (activeInstance) {        document.title = activeInstance.props.title;      }    }  },  getDefaultProps: function () {    return {      title: ''    };  },  isActive: function () {    return this === DocumentTitle.getActiveInstance();  },  componentWillMount: function () {    DocumentTitle.mountedInstances.push(this);    DocumentTitle.updateDocumentTitle();  },  componentDidUpdate: function (prevProps) {    if (this.isActive() && prevProps.title !== this.props.title) {      DocumentTitle.updateDocumentTitle();    }  },  componentWillUnmount: function () {    var index = DocumentTitle.mountedInstances.indexOf(this);    DocumentTitle.mountedInstances.splice(index, 1);    DocumentTitle.updateDocumentTitle();  },  render: function () {    if (this.props.children) {      return Children.only(this.props.children);    } else {      return null;    }  }});module.exports = DocumentTitle;


class Layout extends React.Component {  constructor(props){    super(props);    document.title = this.props.title;  }  render(){    return(      <div>      </div>    );  }}

and then <Layout title="My Title"/> that easy!