Since React doesn't have any builtin way to manage document.title
, I used to set it inside componentDidMount
of my route handlers.
由于React没有任何内置的方法来管理document.title,我曾经在我的路由处理程序的componentDidMount中设置它。
However now I need to amend the title based on state
fetched asynchronously. I started putting assingments into componentDidUpdate
, but every now and then I forget to put document.title
assignment into some pages, and previous title sticks around until I finally notice it.
但是现在我需要根据异步获取的状态修改标题。我开始将assingments放到componentDidUpdate中,但我偶尔忘记将document.title赋值放到某些页面中,之前的标题一直存在,直到我终于注意到它为止。
Ideally I'd like a way to express document.title
declaratively, 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.
子项中指定的标题应覆盖父项指定的标题;
可靠(保证路线变更时的清理);
不应该发出任何DOM(即没有组件返回的hacks
我正在使用react-router,但如果这个组件也可以与其他路由器一起工作,那就更好了。
Anything I can use?
我能用什么?
5 个解决方案
#1
51
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()
.
它提供了一种在单页面应用程序中指定document.title的声明方式。如果要在将组件呈现为字符串后在服务器上获取标题,请调用DocumentTitle.rewind()。
Features
- Does not emit DOM, not even a
<noscript>
; - Like a normal React compoment, can use its parent's
props
andstate
; - 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,甚至不发出
像普通的React组件一样,可以使用其父级的道具和状态;
可以在整个应用程序的许多地方定义;
支持任意级别的嵌套,因此您可以定义应用程序范围和页面特定的标题;
适用于客户端和服务器。
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 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.
我跟踪已安装的实例,并且只有在更新,安装或卸载时才使用已安装的实例堆栈中的*DocumentTitle的标题。在服务器上,componentWillMount会触发,但我们不会获取didMount或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;
#3
6
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!
然后 <布局标题=“我的标题” />这很简单!
#4
4
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,它实际上比反应文档标题更复杂 - 它允许我们更改标题,描述和部分中的任何其他内容。
#5
0
Meanwhile, 3 years have gone! ;-)
If you want to manipulate other page headers than title (like description, canonical, etc.), react-document-meta NPM dependency could be a good thing to use.
与此同时,3年过去了! ;-)如果你想操纵其他页面标题而不是标题(如描述,规范等),react-document-meta NPM依赖可能是一件好事。
#1
51
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()
.
它提供了一种在单页面应用程序中指定document.title的声明方式。如果要在将组件呈现为字符串后在服务器上获取标题,请调用DocumentTitle.rewind()。
Features
- Does not emit DOM, not even a
<noscript>
; - Like a normal React compoment, can use its parent's
props
andstate
; - 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,甚至不发出
像普通的React组件一样,可以使用其父级的道具和状态;
可以在整个应用程序的许多地方定义;
支持任意级别的嵌套,因此您可以定义应用程序范围和页面特定的标题;
适用于客户端和服务器。
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 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.
我跟踪已安装的实例,并且只有在更新,安装或卸载时才使用已安装的实例堆栈中的*DocumentTitle的标题。在服务器上,componentWillMount会触发,但我们不会获取didMount或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;
#2
#3
6
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!
然后 <布局标题=“我的标题” />这很简单!
#4
4
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,它实际上比反应文档标题更复杂 - 它允许我们更改标题,描述和部分中的任何其他内容。
#5
0
Meanwhile, 3 years have gone! ;-)
If you want to manipulate other page headers than title (like description, canonical, etc.), react-document-meta NPM dependency could be a good thing to use.
与此同时,3年过去了! ;-)如果你想操纵其他页面标题而不是标题(如描述,规范等),react-document-meta NPM依赖可能是一件好事。