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

Posted

技术标签:

【中文标题】如何在 React 应用程序中保持 document.title 的更新?【英文标题】:How do I keep document.title updated in React app? 【发布时间】:2014-12-03 16:34:10 【问题描述】:

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

但是现在我需要根据异步获取的state 修改标题。我开始在 componentDidUpdate 中添加分配,但时不时我忘记将 document.title 分配到某些页面中,并且之前的标题一直存在,直到我终于注意到它。

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

在顶层(默认标题); 在页面级别(对于某些页面,但不是全部); 有时,在内部组件级别(例如,用户在字段中输入内容)。

附加要求:

子项中指定的标题应覆盖父项指定的标题; 可靠(保证在更改路线时进行清理); 不应发出任何 DOM(即,没有 hack 组件返回 <noscript>); 我正在使用 react-router,但如果此组件也可以与其他路由器一起使用会更好。

有什么我可以用的吗?

【问题讨论】:

在你的渲染函数中有 document.title = this.state.documentTitle 有什么问题?或者先检查更改做类似的事情。 @Mike:首先,您不应该在render 中这样做,它应该没有副作用。你的意思可能是componentDidUpdate。好吧,随着应用程序的增长,如果您希望它出现在某些屏幕上,那么保持document.title 的一致性变得越来越困难,但对其他屏幕使用一些默认标题。只需要一页就忘记指定标题,它会变得陈旧。 【参考方案1】:

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

【讨论】:

【参考方案2】:
class Layout extends React.Component 
  constructor(props)
    super(props);
    document.title = this.props.title;
  
  render()
    return(
      <div>
      </div>
    );
  

然后&lt;Layout title="My Title"/&gt; 就这么简单!

【讨论】:

【参考方案3】:

看看 NFL 的react-helmet。

【讨论】:

react-helmet 太棒了!【参考方案4】:

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

【讨论】:

【参考方案5】:

我为此写了react-document-title

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

特点

不发出 DOM,甚至不发出 &lt;noscript&gt;; 与普通的 React 组件一样,可以使用其父级的 propsstate; 可以在整个应用程序的许多地方定义; 支持任意级别的嵌套,因此您可以定义应用范围和页面特定的标题; 适用于客户端和服务器。

示例

假设你使用类似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>
    );
  
);

来源

我会跟踪已挂载的实例,并且仅在更新、挂载或卸载时使用分配给已挂载实例堆栈顶部 DocumentTitletitle。在服务器上,componentWillMount 会触发,但我们不会得到didMountwillUnmount,因此我们引入了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;

【讨论】:

亲爱的投票者,您能否提出解决此问题的其他解决方案? 这个 npm 包仍然可以用来设置文档标题吗?我正在使用 React 15.1.0。

以上是关于如何在 React 应用程序中保持 document.title 的更新?的主要内容,如果未能解决你的问题,请参考以下文章

在 React.JS 中刷新后,如何让用户保持登录到 firebase?

Rails+React/Next.js:如何存储代码块以保持格式化?

如何在 React 和 Redux 中保持用户登录,使用 JWT 表达后端应用程序并且没有像 redux-persist 这样的包?

如何使用 aws amplify 保持用户登录 react-native

在组件之间路由时如何保持 React 新的 Context API 状态?

如何在 React.js 中刷新页面后保持状态?