React-router: Recommended way to set document.title?

Created on 25 Jun 2014  Â·  13Comments  Â·  Source: ReactTraining/react-router

Is there a recommended way to set document.title upon routing? I suppose one could just set it in all of the componentDidMount handlers, but it might be nice if there was a general strategy for this. (For example, maybe one page doesn't really care about title, in which case we'd want to fall back to the default.)

(Someone was also asking in IRC about this last night right after you left, @rpflorence.)

Most helpful comment

@mjackson @rpflorence

I put it on NPM as react-document-title.
It really plays well with react-router's nesting:

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>
    );
  }
});

All 13 comments

componentDidMount seems good?

var Handler = React.createClass({
  componentDidMount: function() {
    document.title = "Amazing Page";
  }
});

Often it will probably depend on data you fetch though:

var Handler = React.createClass({
  componentDidMount: function() {
    someStore.fetchStuff(this.params.id, function(data) {
      this.setState({data: data});
      document.title = "Amazing Page | " + data.name;
    }.bind(this));
  }
});

Since I can't imagine all the scenarios that go into deciding what your page title is, and since you generally aren't serializing state to the <head> and <title> tags, I don't expect to have a conventional way to do this.

I think just doing document.title wherever you want is enough.

Eventually we will have a server-rendering story/example, so in that case you'd probably want a helper function that is a noop when on the server.

Eventually we will have a server-rendering story/example, so in that case you'd probably want a helper function that is a noop when on the server.

Ideally the server-rendered markup can have the right title too. :)

I've messed with React.renderComponent(<App/>, document.documentElement)
and it almost works, I don't think you'll ever own anything higher than
body.

On Wed, Jun 25, 2014 at 4:00 PM, Ben Alpert [email protected]
wrote:

Eventually we will have a server-rendering story/example, so in that case
you'd probably want a helper function that is a noop when on the server.

Ideally the server-rendered markup can have the right title too. :)

—
Reply to this email directly or view it on GitHub
https://github.com/rpflorence/react-nested-router/issues/49#issuecomment-47164572
.

I prefer the declarative way:

// there was some outdated code here, see below now

@gaearon boom. that's the way to do it!

@mjackson @rpflorence

I put it on NPM as react-document-title.
It really plays well with react-router's nesting:

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>
    );
  }
});

Thanks to @pluma, react-document-title now supports server-side usage via DocumentTitle.rewind() method. So, just like react-router, it can be used on both sides.

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

then <Layout title="My Title"/> it works!

Hi @rajeshkw
I found better solution, that works with fetching data and Redux

import React from 'react';

export default class Layout extends React.Component {
  constructor(props){
    super(props);
  }
  componentWillUpdate(nextProps) {
    document.title = nextProps.title;
  }
  render(){
    return null;
  }
}

How do you do this in stateless functional components? I tried this but it doesn't work:
ComponentName.componentDidMount = () => document.title = "Who's Marco?"
Where the ComponentName is something like this:

export const Life = ({sayHello="Ciao"}) => (

)

@marcogreselin , As I know we can't create lifecycle hooks in a stateless functional component, These functional components don't have backing instances, and do not have the component lifecycle methods too. So better to convert it to stateful class style component.

@marcogreselin not sure if it's the right way but I believe you can do something like this.

export const Life = ({sayHello="Ciao"}) => {
  document.title='Your title.';
  return (
    <Your JSX>
  );
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

imWildCat picture imWildCat  Â·  3Comments

winkler1 picture winkler1  Â·  3Comments

ryansobol picture ryansobol  Â·  3Comments

ackvf picture ackvf  Â·  3Comments

wzup picture wzup  Â·  3Comments