你如何在 React 中设置文档标题?

Posted

技术标签:

【中文标题】你如何在 React 中设置文档标题?【英文标题】:How do you set the document title in React? 【发布时间】:2018-02-19 23:25:59 【问题描述】:

我想为我的 React 应用程序设置文档标题(在浏览器标题栏中)。我尝试使用react-document-title(似乎已过时)并在constructorcomponentDidMount() 中设置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 设置一个 标签似乎有点过头了。 @nxmohamad 是的,“flash”问题可以通过从 index.html 文件中完全删除标题标签来解决。唯一的缺点是您必须确保在每个页面上都给出一个标题,否则它默认为域名。【参考方案3】:

对于 React 16.8,您可以使用 useEffect 使用功能组件来执行此操作。

例如:

useEffect(() => 
   document.title = "new title"
, []);

将第二个参数作为数组只调用一次useEffect,使其类似于componentDidMount

【讨论】:

如何用笑话和酶来测试?【参考方案4】:

正如其他人所提到的,您可以使用document.title = 'My new title' 和React Helmet 来更新页面标题。这两种解决方案仍然会在加载脚本之前呈现初始的“React App”标题。

如果您使用create-react-app,则初始文档标题在&lt;title&gt;标签/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 节点之外的元素(例如 &lt;title&gt;),就好像它们是实际的 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 的 &lt;title&gt;Default Title&lt;/title&gt; 中已经找到的内容。 只需删除模块中的默认标题(不在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>
        </>
    

不知道为什么其他人热衷于将他们的整个应用程序放入他们的&lt;Title&gt; 组件,这对我来说似乎很奇怪。

通过更新render() 内的document.title,如果您想要动态标题,它将刷新/保持最新状态。卸载时它也应该恢复标题。传送门很可爱,但似乎没有必要;我们真的不需要在这里操作任何 DOM 节点。

【讨论】:

【参考方案14】:

您可以使用 ReactDOM 并更改 &lt;title&gt; 标签

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 中设置文档标题?的主要内容,如果未能解决你的问题,请参考以下文章

你如何在反应中设置一个组件与不同组件的状态?

如何在打字稿中设置初始 React 状态?

如何在钩子中设置值

如何在 React 中设置电话号码输入样式?

如何在 react-select 中设置默认值

如何在 React 子组件中设置事件处理程序