javascript 如何在 React 应用程序中保持 document.title 更新?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26266675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 05:44:50  来源:igfitidea点击:

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

javascriptdomreactjsreact-router

提问by Dan Abramov

Since React doesn't have any builtin way to manage document.title, I used to set it inside componentDidMountof my route handlers.

由于 React 没有任何内置方式来管理document.title,我曾经在componentDidMount我的路由处理程序中设置它。

However now I need to amend the title based on statefetched asynchronously. I started putting assingments into componentDidUpdate, but every now and then I forget to put document.titleassignment into some pages, and previous title sticks around until I finally notice it.

但是现在我需要根据state异步获取来修改标题。我开始把assingments成componentDidUpdate,但每一个现在,然后我忘了把document.title分配到一些网页,和周围,直到我终于发现它以前的标题棒。

Ideally I'd like a way to express document.titledeclaratively, without having to assign it. Some kind of “fake” component would probably be most convenient, given that I want to be able to specify the document title at several nesting levels:

理想情况下,我想要一种document.title无需分配即可声明式表达的方式。考虑到我希望能够在多个嵌套级别指定文档标题,某种“假”组件可能是最方便的:

  • On top level (the default title);
  • On page level (for some of the pages, but not all);
  • Sometimes, on inner component level (e.g. user typing into a field).
  • 在顶层(默认标题);
  • 在页面级别(对于某些页面,但不是全部);
  • 有时,在内部组件级别(例如用户输入字段)。

Additional requirements:

其他要求:

  • Title specified in child should override title specified by parent;
  • Reliable (guarantees cleanup on route change);
  • Should not emit any DOM (i.e. no hacks with component returning <noscript>);
  • I'm using react-router but it's better if this component works with other routers too.
  • child 中指定的 title 应该覆盖 parent 中指定的 title;
  • 可靠(保证路线改变时的清理);
  • 不应发出任何 DOM(即没有组件返回的 hacks <noscript>);
  • 我正在使用 react-router 但如果这个组件也能与其他路由器一起使用会更好。

Anything I can use?

有什么我可以用的吗?

回答by Dan Abramov

I wrote react-document-titlejust for that.

我为此编写了react-document-title

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

它提供了一种document.title在单页应用程序中指定的声明方式。
如果您想在将组件渲染为字符串后在服务器上获得标题,请调用DocumentTitle.rewind().

Features

特征

  • Does not emit DOM, not even a <noscript>;
  • Like a normal React compoment, can use its parent's propsand 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.
  • 不发出 DOM,甚至不发出<noscript>;
  • 像普通的 React 组件一样,可以使用其父级的propsand state;
  • 可以在整个应用程序的很多地方定义;
  • 支持任意级别的嵌套,因此您可以定义应用程序范围和页面特定的标题;
  • 适用于客户端和服务器。

Example

例子

Assuming you use something like react-router:

假设你使用类似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 titlegiven to the top DocumentTitlein the mounted instance stack whenever it updates, gets mounted or unmounted. On server, componentWillMountfires but we won't get didMountor willUnmount, so we introduce DocumentTitle.rewind()that returns a string and destroys state to prepare for next request.

我跟踪已安装的实例,并且仅在它更新、安装或卸载时才使用已安装实例堆栈中title的顶部DocumentTitle。在服务器上,componentWillMount触发但我们不会得到didMountor willUnmount,因此我们引入DocumentTitle.rewind()返回一个字符串并破坏状态以准备下一个请求。

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;

回答by dbkaplun

Take a look at the NFL's react-helmet.

看看 NFL 的react-helmet

回答by rajesh_kw

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!

然后就<Layout title="My Title"/>这么简单!

回答by Vadim Guzev

Try react-frozenhead, it's actually more sophisticated than react-document-title - it allows us change title, description and anything else in section.

尝试react-frozenhead,它实际上比 react-document-title 更复杂 - 它允许我们更改部分中的标题、描述和其他任何内容。

回答by Pedro Ferreira

Meanwhile, 3 years have gone! ;-)
If you want to manipulate other page headers than title (like description, canonical, etc.), react-document-metaNPM dependency could be a good thing to use.

与此同时,3年过去了!;-)
如果你想操作除标题之外的其他页眉(如描述、规范等),react-document-metaNPM 依赖可能是一个很好的选择。