你如何在 React 中设置文档标题?
Posted
技术标签:
【中文标题】你如何在 React 中设置文档标题?【英文标题】:How do you set the document title in React? 【发布时间】:2018-02-19 23:25:59 【问题描述】:我想为我的 React 应用程序设置文档标题(在浏览器标题栏中)。我尝试使用react-document-title(似乎已过时)并在constructor
和componentDidMount()
中设置document.title
- 这些解决方案都不起作用。
【问题讨论】:
我确认,react-document-title 适用于 react 16.5 【参考方案1】:import React from 'react'
import ReactDOM from 'react-dom'
class Doc extends React.Component
componentDidMount()
document.title = "dfsdfsdfsd"
render()
return(
<b> test </b>
)
ReactDOM.render(
<Doc />,
document.getElementById('container')
);
这对我有用。
编辑:如果你使用 webpack-dev-server 设置 inline 为 true
【讨论】:
这可行,但在页面加载时文档标题仍然是“React App” - 知道如何解决这个问题吗? 更改 index.html 中标题标签的内容 最好像@quotesBro's answer中那样以声明方式进行 这种方式适合 SEO 吗? @AlexVestin 如果您的 React 应用程序中的不同视图需要不同的标题,这不是一个好主意【参考方案2】:你可以使用React Helmet:
import React from 'react'
import Helmet from 'react-helmet'
const TITLE = 'My Page Title'
class MyComponent extends React.PureComponent
render ()
return (
<>
<Helmet>
<title> TITLE </title>
</Helmet>
...
</>
)
【讨论】:
这会在第一秒“闪现”index.html 的内容,对吧? 这绝对应该是最佳答案。这是管理标题和其他元属性的绝佳声明方式 在 React 16 中使用头盔有问题 github.com/nfl/react-helmet/issues/548 设置一个对于 React 16.8,您可以使用 useEffect 使用功能组件来执行此操作。
例如:
useEffect(() =>
document.title = "new title"
, []);
将第二个参数作为数组只调用一次useEffect,使其类似于componentDidMount
。
【讨论】:
如何用笑话和酶来测试?【参考方案4】:正如其他人所提到的,您可以使用document.title = 'My new title'
和React Helmet 来更新页面标题。这两种解决方案仍然会在加载脚本之前呈现初始的“React App”标题。
如果您使用create-react-app
,则初始文档标题在<title>
标签/public/index.html
文件中设置。
您可以直接编辑它或使用将从环境变量中填充的占位符:
/.env
:
REACT_APP_SITE_TITLE='My Title!'
SOME_OTHER_VARS=...
如果出于某种原因我想在我的开发环境中使用不同的标题 -
/.env.development
:
REACT_APP_SITE_TITLE='**DEVELOPMENT** My TITLE! **DEVELOPMENT**'
SOME_OTHER_VARS=...
/public/index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
...
<title>%REACT_APP_SITE_TITLE%</title>
...
</head>
<body>
...
</body>
</html>
这种方法还意味着我可以使用全局 process.env
对象从我的应用程序中读取站点标题环境变量,这很好:
console.log(process.env.REACT_APP_SITE_TITLE_URL);
// My Title!
见:Adding Custom Environment Variables
【讨论】:
确保将 .env 文件放在 package.json 文件的同一级别。 :) 我试过了,但 %REACT_APP_SITE_TITLE% 显示为标题。我将 .env 保持在与 package.json 相同的级别并使用 react-scripts 3.4.1 @YuvrajPatil 这仅在构建时应用。如果您需要在运行时注入它们,create-react-app.dev/docs/… 我相信这是最合理的解决方案,除非您想更改组件内的标题【参考方案5】:从 React 16.8 开始。您可以构建一个自定义钩子来这样做(类似于@Shortchange的解决方案):
export function useTitle(title)
useEffect(() =>
const prevTitle = document.title
document.title = title
return () =>
document.title = prevTitle
)
这可以在任何反应组件中使用,例如:
const MyComponent = () =>
useTitle("New Title")
return (
<div>
...
</div>
)
它会在组件安装后立即更新标题,并在卸载时将其恢复为之前的标题。
【讨论】:
如果我错了,请纠正我,但这仅适用于 Function 组件,不适用于 Class 组件。 现代 React 的最佳答案!重置标题的想法很棒。 很棒的钩子,在函数组件中效果很好。正如 Alex 已经告诉我们的那样,它在类组件中不起作用,我只是做了一个测试以确保。 此解决方案不应该将依赖项设置为 [] 以便仅在挂载和卸载时运行吗? 这是迄今为止最好的解决方案。好东西。跟上【参考方案6】:React Portals 可以让您渲染到根 React 节点之外的元素(例如 <title>
),就好像它们是实际的 React 节点一样。所以现在你可以干净地设置标题,而无需任何额外的依赖:
这是一个例子:
import React, Component from 'react';
import ReactDOM from 'react-dom';
class Title extends Component
constructor(props)
super(props);
this.titleEl = document.getElementsByTagName("title")[0];
render()
let fullTitle;
if(this.props.pageTitle)
fullTitle = this.props.pageTitle + " - " + this.props.siteTitle;
else
fullTitle = this.props.siteTitle;
return ReactDOM.createPortal(
fullTitle || "",
this.titleEl
);
Title.defaultProps =
pageTitle: null,
siteTitle: "Your Site Name Here",
;
export default Title;
只需将组件放入页面并设置pageTitle
:
<Title pageTitle="Dashboard" />
<Title pageTitle=item.name />
【讨论】:
哇,看起来很有前途,React Helmet 和 document.title 都可以,但这太棒了:) 谢谢 我喜欢这个解决方案,直到我意识到它只是将fullTitle
附加到 index.html 的 <title>Default Title</title>
中已经找到的内容。
只需删除模块中的默认标题(不在constructor
!)``` import React from 'react';从 'prop-types' 导入 PropTypes;从“react-dom”导入 ReactDOM; const titleNode = document.getElementsByTagName("title")[0]; titleNode.innerText = '';导出默认类 Title 扩展 React.PureComponent static propTypes = children: PropTypes.node, ;构造函数(道具)超级(道具); this.el = 标题节点; render() return ReactDOM.createPortal( this.props.children, this.el, ); ```【参考方案7】:
如果你想知道,你可以直接在渲染函数里面设置:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component
render()
document.title = 'wow'
return <p>Hello</p>
ReactDOM.render(
<App />,
document.getElementById('root')
)
对于功能组件:
function App()
document.title = 'wow'
return <p>Hello</p>
但是,正如 Elias 在评论中所说,这是一种不好的做法。
良好做法:
类组件:
class App extends React.Component
// you can also use componentDidUpdate() if the title is not static
componentDidMount()
document.title = "good"
render()
return <p>Hello</p>
功能组件:
function App()
// for static title, pass an empty array as the second argument
// for dynamic title, put the dynamic values inside the array
// see: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
useEffect(() =>
document.title = 'good'
, []);
return <p>Hello</p>
【讨论】:
这是一个出现在许多 React 代码库中的典型错误:不要这样做!每个渲染方法都应该是纯函数(无副作用),如果您需要执行副作用:useEffect 用于功能组件或类中的组件事件(更多信息:reddit.com/r/reactjs/comments/8avfej/…) +1 对 Elias 的评论。即使您列出了正确的方法,此答案也可能导致人们将其放入render
func。【参考方案8】:
import React from 'react';
function useTitle(title: string): void =>
React.useEffect(() =>
const prevTitle = document.title;
document.title = title;
return () =>
document.title = prevTitle;
;
, []);
function MyComponent(): JSX.Element =>
useTitle('Title while MyComponent is mounted');
return <div>My Component</div>;
这是一个非常直接的解决方案,useTitle
设置文档标题,当组件卸载时,它会重置为之前的任何内容。
【讨论】:
这是正确的做法。但是,不必这样做肯定会很好。这个概念可重复使用,只需在 npm 上即可。【参考方案9】:你应该在'componentWillMount'的生命周期中设置文档标题:
componentWillMount()
document.title = 'your title name'
,
【讨论】:
componentWillMount() 在最新的 React 版本 16 中已弃用 在这种情况下,与大多数情况一样,当您必须删除已弃用的 componentWillMount 时,请将您的代码移动到 componentDidMount【参考方案10】:只需在 js 文件中创建一个函数并将其导出以在组件中使用
如下:
export default function setTitle(title)
if (typeof title !== "string")
throw new Error("Title should be an string");
document.title = title;
并在这样的任何组件中使用它:
import React, Component from 'react';
import setTitle from './setTitle.js' // no need to js extension at the end
class App extends Component
componentDidMount()
setTitle("i am a new title");
render()
return (
<div>
see the title
</div>
);
export default App
【讨论】:
【参考方案11】:您可以将以下内容与document.title = 'Home Page'
一起使用
import React from 'react'
import Component from 'react-dom'
class App extends Component
componentDidMount()
document.title = "Home Page"
render()
return(
<p> Title is now equal to Home Page </p>
)
ReactDOM.render(
<App />,
document.getElementById('root')
);
或者你可以使用这个 npm 包npm i react-document-title
import React from 'react'
import Component from 'react-dom'
import DocumentTitle from 'react-document-title';
class App extends Component
render()
return(
<DocumentTitle title='Home'>
<h1>Home, sweet home.</h1>
</DocumentTitle>
)
ReactDOM.render(
<App />,
document.getElementById('root')
);
编码愉快!!!
【讨论】:
【参考方案12】:对于这个问题,您有多种选择,我强烈建议您使用React Helmet
或使用useEffect
创建一个挂钩。您也可以使用来自react-use
的钩子,而不是编写自己的钩子:
React Helmet
import React from 'react';
import Helmet from 'react-helmet';
const MyComponent => () => (
<Helmet>
<title>My Title</title>
</Helmet>
)
react-use
import React from 'react';
import useTitle from 'react-use';
const MyComponent = () =>
useTitle('My Title');
return null;
【讨论】:
【参考方案13】:我没有对此进行过彻底的测试,但这似乎有效。用 TypeScript 编写。
interface Props
children: string|number|Array<string|number>,
export default class DocumentTitle extends React.Component<Props>
private oldTitle: string = document.title;
componentWillUnmount(): void
document.title = this.oldTitle;
render()
document.title = Array.isArray(this.props.children) ? this.props.children.join('') : this.props.children;
return null;
用法:
export default class App extends React.Component<Props, State>
render()
return <>
<DocumentTitle>this.state.files.length Gallery</DocumentTitle>
<Container>
Lorem ipsum
</Container>
</>
不知道为什么其他人热衷于将他们的整个应用程序放入他们的<Title>
组件,这对我来说似乎很奇怪。
通过更新render()
内的document.title
,如果您想要动态标题,它将刷新/保持最新状态。卸载时它也应该恢复标题。传送门很可爱,但似乎没有必要;我们真的不需要在这里操作任何 DOM 节点。
【讨论】:
【参考方案14】:您可以使用 ReactDOM 并更改 <title>
标签
ReactDOM.render(
"New Title",
document.getElementsByTagName("title")[0]
);
【讨论】:
【参考方案15】:Helmet 确实是一个很好的方法,但是对于只需要更改标题的应用程序,这是我使用的: (现代方式 React 解决方案 - 使用 Hooks)
-
创建更改页面标题组件
import React, useEffect from "react";
const ChangePageTitle = ( pageTitle ) =>
useEffect(() =>
const prevTitle = document.title;
document.title = pageTitle;
return () =>
document.title = prevTitle;
;
);
return <></>;
;
export default ChangePageTitle;
-
使用组件
import ChangePageTitle from "../yourLocation/ChangePageTitle";
...
return (
<>
<ChangePageTitle pageTitle="theTitleYouWant" />
...
</>
);
...
【讨论】:
【参考方案16】:我使用这种方法,我发现它对我来说更容易。 我将它与功能组件结合使用。 只有在您不关心如果用户在您的页面上禁用 Javascript 时它不会显示任何标题时才这样做。
你需要做两件事。
1.进入你的 index.html 并在此处删除这一行
<title>React App</title>
2.进入你的mainapp函数并返回这只是一个普通的html结构,你可以从你的网站复制并粘贴你的主要内容到body标签之间:
return (
<html>
<head>
<title>hi</title>
</head>
<body></body>
</html>
);
你可以随意替换标题。
【讨论】:
【参考方案17】:最简单的方法是使用 react-document-configuration
npm install react-document-configuration --save
示例:
import React from "react";
import Head from "react-document-configuration";
export default function Application()
return (
<div>
<Head title="HOME" icon="link_of_icon" />
<div>
<h4>Hello Developers!</h4>
</div>
</div>
);
;```
【讨论】:
【参考方案18】:const [name, setName] = useState("Jan");
useEffect(() =>
document.title = "Celebrate " + name.name ;
);
【讨论】:
如果您解释您的代码示例并将其放入问题的上下文中,则更容易接受这样的答案。useEffect
也被Jordan Daniels 等人在this answer 中推荐过。请edit您的答案解释一下您的答案与他们的答案有何不同?【参考方案19】:
我想在我的常见问题页面中使用页面标题。所以我为此使用了 react-helmet。
首先我使用 npm i react-helmet
安装了 react-helmet然后我在我的退货中添加了这样的标签:
从“反应”导入反应 从'react-helmet'导入头盔 const PAGE_TITLE = '常见问题页面' 导出默认类 FAQ 扩展组件 渲染 () 返回 ( 页面标题 这是我的常见问题页面 )【讨论】:
【参考方案20】:如果您是初学者,您可以通过转到您的 react 项目文件夹的公共文件夹并在“index.html”中编辑标题并放入您的标题来避免所有这些。不要忘记保存以便它反映。
【讨论】:
以上是关于你如何在 React 中设置文档标题?的主要内容,如果未能解决你的问题,请参考以下文章