คุณตั้งชื่อเอกสารใน React ได้อย่างไร?


125

ฉันต้องการตั้งชื่อเอกสาร (ในแถบชื่อเรื่องของเบราว์เซอร์) สำหรับแอปพลิเคชัน React ของฉัน ฉันได้ลองใช้react-document-title (ดูเหมือนล้าสมัย) และการตั้งค่าdocument.titleในconstructorและcomponentDidMount()- ไม่มีวิธีแก้ปัญหาเหล่านี้


ตกยุค? @DanAbramov ฉันเดาว่า react-document-title ทำงานได้ดีกับ React16 เช่นกัน
JS dev

ฉันยืนยันว่า react-document-title ใช้งานได้ดีกับ react 16.5
DevTheJo

คำตอบ:


98

คุณสามารถใช้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>
        ...
      </>
    )
  }
}

1
สิ่งนี้จะ "กะพริบ" เนื้อหาของ index.html ในวินาทีแรกใช่ไหม
nxmohamad

3
นี่น่าจะเป็นคำตอบอันดับต้น ๆ แน่นอน เป็นวิธีการประกาศที่ยอดเยี่ยมในการจัดการชื่อเรื่องและคุณสมบัติเมตาอื่น ๆ
Ryall

129
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 ตั้งค่าในบรรทัดเป็นจริง


5
วิธีนี้ใช้งานได้ แต่ชื่อเอกสารยังคงเป็น "React App" ในขณะที่หน้ากำลังโหลด - มีความคิดอย่างไรในการแก้ไข
eli

8
เปลี่ยนเนื้อหาของแท็กหัวเรื่องใน index.html ของคุณ
AlexVestin

4
ดีกว่าที่จะทำอย่างเปิดเผยเหมือนในคำตอบของ @ quotesBro
Ryall

1
วิธีนี้ใช้ได้กับ SEO หรือไม่?
Davidm176

@AlexVestin ไม่ใช่ความคิดที่ดีหากคุณต้องการชื่อที่แตกต่างกันสำหรับมุมมองที่แตกต่างกันในแอปพลิเคชัน React ของคุณ
Kevin

63

สำหรับการตอบสนอง 16.8 คุณสามารถทำเช่นนี้กับองค์ประกอบการทำงานโดยใช้useEffect

ตัวอย่างเช่น:

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

การมีอาร์กิวเมนต์ที่สองเป็นอาร์เรย์เรียกใช้ useEffect เพียงครั้งเดียวทำให้คล้ายกับcomponentDidMount.


วิธีนี้ทดสอบกับ jest และ enzyme ได้อย่างไร?
nickstaroba

20

ดังที่คนอื่น ๆ ได้กล่าวถึงคุณสามารถใช้document.title = 'My new title'และตอบสนองหมวกกันน็อคเพื่ออัปเดตชื่อเพจได้ โซลูชันทั้งสองนี้จะยังคงแสดงชื่อ '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!

ดู: การเพิ่มตัวแปรสภาพแวดล้อมแบบกำหนดเอง


อย่าลืมใส่ไฟล์. env ที่ระดับเดียวกับไฟล์ package.json ของคุณ :)
Ian Smith

ฉันลองแล้ว แต่% REACT_APP_SITE_TITLE% แสดงเป็นชื่อ ฉันเก็บ. env ไว้ในระดับเดียวกับ package.json และใช้ react-scripts 3.4.1
Yuvraj Patil

10

คุณควรตั้งชื่อเอกสารในวงจรชีวิตของ 'componentWillMount':

componentWillMount() {
    document.title = 'your title name'
  },

10
componentWillMount () เลิกใช้งานในเวอร์ชันตอบสนองล่าสุด 16
Hemadri Dasari

3
ในกรณีนี้เช่นเดียวกับในกรณีส่วนใหญ่เมื่อคุณต้องลบ componentWillMount ที่เลิกใช้แล้วให้ย้ายรหัสของคุณไปที่ componentDidMount
DevTheJo

10

React Portalsสามารถให้คุณแสดงผลไปยังองค์ประกอบภายนอกโหนด React root (เช่นที่<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 ใช้งานได้ทั้งคู่ แต่มันยอดเยี่ยมมาก :) ขอบคุณ
mamsoudi

ฉันรักการแก้ปัญหานี้จนกว่าฉันจะรู้ว่ามันเป็นเพียงผนวกfullTitleกับเนื้อหาที่พบแล้วใน <title>Default Title</title>index.html
JWess

เพียงแค่ลบชื่อเริ่มต้นในโมดูลของคุณ (ไม่ใช่ในconstructor!) `` นำเข้าปฏิกิริยาจาก 'ตอบสนอง'; นำเข้า PropTypes จาก 'prop-types'; นำเข้า ReactDOM จาก 'react-dom'; const titleNode = document.getElementsByTagName ("ชื่อเรื่อง") [0]; titleNode.innerText = ''; ส่งออกคลาสเริ่มต้น Title ขยาย React.PureComponent {static propTypes = {children: PropTypes.node,}; คอนสตรัคเตอร์ (อุปกรณ์ประกอบฉาก) {super (props); this.el = titleNode; } render () {return ReactDOM.createPortal (this.props.children, this.el,); }} ``
Anatoliy Litinskiy

9

ใน React 16.13 คุณสามารถตั้งค่าได้โดยตรงในฟังก์ชัน render:

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>
}

2
นี่เป็นข้อผิดพลาดทั่วไปที่ปรากฏในฐานรหัสการตอบสนองหลายอย่าง: อย่าทำอย่างนั้น! ทุกวิธีการเรนเดอร์ควรเป็นฟังก์ชันที่บริสุทธิ์ (ไม่มีผลข้างเคียง) หากคุณต้องการใช้ผลข้างเคียง: useEffect สำหรับส่วนประกอบที่ใช้งานได้หรือเหตุการณ์ของส่วนประกอบในชั้นเรียน (ข้อมูลเพิ่มเติม: reddit.com/r/reactjs/comments/8avfej/… )
Elias Platek

7

ตั้งแต่ React 16.8.2 คุณสามารถสร้างเบ็ดแบบกำหนดเองได้ (คล้ายกับโซลูชันของ @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>
  )
}

มันจะอัปเดตหัวเรื่องทันทีที่คอมโพเนนต์ติดตั้งและเปลี่ยนกลับเป็นชื่อก่อนหน้าเมื่อยกเลิกการต่อเชื่อม


6

เพียงแค่คุณสร้างฟังก์ชันในไฟล์ 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

3

คุณสามารถใช้สิ่งต่อไปนี้ด้านล่างกับ 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')
);

Happy Coding !!!


2

ฉันยังไม่ได้ทดสอบสิ่งนี้อย่างละเอียดเกินไป แต่ดูเหมือนว่าจะได้ผล เขียนใน 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>ส่วนประกอบของพวกเขาซึ่งดูแปลกสำหรับฉัน

การอัปเดตdocument.titleภายในrender()จะทำให้รีเฟรช / อัปเดตอยู่เสมอหากคุณต้องการชื่อแบบไดนามิก ควรเปลี่ยนชื่อกลับเมื่อยกเลิกการต่อเชื่อมด้วย พอร์ทัลน่ารัก แต่ดูเหมือนไม่จำเป็น เราไม่จำเป็นต้องจัดการกับโหนด DOM ที่นี่



2
const setTitle = (title) => {
  const prevTitle = document.title;
  document.title = title;
  return () => document.title = prevTitle;
}

const MyComponent = () => {
  useEffect(() => setTitle('Title while MyComponent is mounted'), []);

  return <div>My Component</div>;
}

นี่เป็นวิธีแก้ปัญหาที่ค่อนข้างตรงไปตรงมาที่ฉันได้พูดคุยกันขณะทำงานในวันนี้ setTitleส่งคืนฟังก์ชันที่รีเซ็ตชื่อเป็นสิ่งที่เคยใช้ก่อนหน้าsetTitleนี้ทำงานได้อย่างยอดเยี่ยมภายในuseEffectเบ็ดของ React


1
นี่คือวิธีทำที่ถูกต้อง แต่มันคงจะดีไม่น้อยที่จะต้องทำ แนวคิดนี้สามารถใช้ซ้ำได้เพียงพอที่จะอยู่บน npm
Eugene Kuzmenko

0

ฉันใช้วิธีนี้ซึ่งฉันพบว่ามันง่ายกว่าสำหรับฉัน ฉันใช้มันร่วมกับส่วนประกอบของฟังก์ชัน ทำสิ่งนี้เฉพาะในกรณีที่คุณไม่สนใจว่าจะไม่แสดงชื่อเรื่องใด ๆ หากผู้ใช้ปิดใช้งาน Javascript บนเพจของคุณ

มีสองสิ่งที่คุณต้องทำ

1. เข้าไปที่ index.html ของคุณและลบบรรทัดนี้ที่นี่

<title>React App</title>

2. ไปที่ฟังก์ชัน mainapp ของคุณและส่งคืนสิ่งนี้ซึ่งเป็นเพียงโครงสร้าง html ปกติคุณสามารถคัดลอกและวางเนื้อหาหลักของคุณจากเว็บไซต์ของคุณระหว่างแท็กเนื้อหา:

return (
        <html>
          <head>
            <title>hi</title>
          </head>
          <body></body>
        </html>
      );

คุณสามารถเปลี่ยนชื่อได้ตามที่คุณต้องการ


-8

หากคุณเป็นมือใหม่คุณก็สามารถช่วยตัวเองจากสิ่งเหล่านั้นได้โดยไปที่โฟลเดอร์สาธารณะของโฟลเดอร์ react project ของคุณและแก้ไขชื่อใน "index.html" และใส่ชื่อของคุณ อย่าลืมบันทึกจึงจะสะท้อน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.