Jak ustawić tytuł dokumentu w React?

113

Chciałbym ustawić tytuł dokumentu (w pasku tytułu przeglądarki) dla mojej aplikacji React. Próbowałem użyć react-document-title (wydaje się nieaktualne) i ustawienia document.titlew constructorand componentDidMount()- żadne z tych rozwiązań nie działa.

eli
źródło
przeterminowany? @DanAbramov Myślę, że React-document-title działa również dobrze z React16.
JS dev
Potwierdzam, reakcja-dokument-tytuł działa świetnie z
React

Odpowiedzi:

89

Możesz użyć 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>
        ...
      </>
    )
  }
}
quotesBro
źródło
1
spowoduje to „flashowanie” zawartości pliku index.html w pierwszej sekundzie, prawda?
nxmohamad
3
To zdecydowanie powinna być najlepsza odpowiedź. To doskonały, deklaratywny sposób zarządzania tytułem i innymi atrybutami meta
Ryall
117
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')
);

To działa dla mnie.

Edycja: jeśli używasz pakietu webpack-dev-server, ustaw inline na true

AlexVestin
źródło
5
To działa, ale podczas wczytywania strony tytuł dokumentu nadal brzmi „React App” - czy masz pomysł, jak to naprawić?
eli
7
Zmień zawartość tagu tytułu w
pliku
4
Lepiej to zrobić deklaratywnie jak w @ odpowiedź quotesBro za
Ryall
1
Czy ten sposób jest odpowiedni dla SEO?
Davidm176
@AlexVestin Nie jest to dobry pomysł, jeśli potrzebujesz różnych tytułów dla różnych widoków w swojej aplikacji React
Kevin
55

W przypadku React 16.8 możesz to zrobić za pomocą komponentu funkcjonalnego za pomocą useEffect .

Na przykład:

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

Posiadanie drugiego argumentu jako tablicy wywołuje useEffect tylko raz, czyniąc go podobnym do componentDidMount.

Jordan Daniels
źródło
Jak można to sprawdzić żartem i enzymem?
nickstaroba
20

Jak wspominali inni, możesz użyć document.title = 'My new title'i React Helmet, aby zaktualizować tytuł strony. Oba te rozwiązania będą nadal renderować początkowy tytuł „React App” przed załadowaniem skryptów.

Jeśli używasz Początkowy tytuł dokumentu znajduje się w tagu pliku.create-react-app<title>/public/index.html

Możesz to edytować bezpośrednio lub użyć symbolu zastępczego, który zostanie wypełniony ze zmiennych środowiskowych:

/.env:

REACT_APP_SITE_TITLE='My Title!'
SOME_OTHER_VARS=...

Gdybym z jakiegoś powodu chciał mieć inny tytuł w moim środowisku deweloperskim -

/.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>

Takie podejście oznacza również, że mogę odczytać zmienną środowiskową tytułu witryny z mojej aplikacji za pomocą process.envobiektu globalnego , co jest miłe:

console.log(process.env.REACT_APP_SITE_TITLE_URL);
// My Title!

Zobacz: Dodawanie niestandardowych zmiennych środowiskowych

Szorstki
źródło
Upewnij się, że pliki .env znajdują się na tym samym poziomie, co plik package.json. :)
Ian Smith
10

powinieneś ustawić tytuł dokumentu w cyklu życia „componentWillMount”:

componentWillMount() {
    document.title = 'your title name'
  },
Alvin
źródło
9
KomponentWillMount () jest przestarzały w najnowszej wersji
React
3
W takim przypadku, jak w większości przypadków, kiedy musisz usunąć przestarzały komponentWillMount, przenieś swój kod do componentDidMount
DevTheJo
10

Portale React umożliwiają renderowanie elementów poza głównym węzłem React (np. At <title>), tak jakby były rzeczywistymi węzłami React. Więc teraz możesz ustawić tytuł czysto i bez żadnych dodatkowych zależności:

Oto przykład:

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;

Po prostu umieść komponent na stronie i ustaw pageTitle:

<Title pageTitle="Dashboard" />
<Title pageTitle={item.name} />
Pułkownik trzydzieści dwa
źródło
Wow, wygląda tak obiecująco, React kask i document.title zarówno pracę, ale to jest niesamowite :) Dzięki
mamsoudi
Uwielbiałem to rozwiązanie, dopóki nie zdałem sobie sprawy, że po prostu dołącza fullTitlesię do treści już znalezionych w pliku index.html <title>Default Title</title>.
JWess
Po prostu usuń domyślny tytuł w swoim module (nie w constructor!) `` Importuj React z 'reaguj'; import PropTypes z 'prop-types'; importuj ReactDOM z „React-dom”; const titleNode = document.getElementsByTagName ("tytuł") [0]; titleNode.innerText = ''; eksport domyślnej klasy Title rozszerza React.PureComponent {static propTypes = {dzieci: PropTypes.node,}; konstruktor (props) {super (props); this.el = titleNode; } render () {return ReactDOM.createPortal (this.props.children, this.el,); }} ``
Anatoliy Litinskiy
10

W Reakcie 16.13 możesz ustawić to bezpośrednio w funkcji renderowania:

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')
)

Dla komponentu funkcyjnego:

function App() {
    document.title = 'wow'
    return <p>Hello</p>
}
M Imam Pratama
źródło
1
Jest to typowy błąd, który pojawia się w wielu bazach kodu reakcji: NIE ROBIĆ TEGO! Każda metoda renderowania powinna być czystymi funkcjami (bez efektów ubocznych), jeśli potrzebujesz wykonać efekt uboczny: useEffect dla komponentów funkcjonalnych, czy zdarzenia komponentów w klasach (więcej informacji: reddit.com/r/reactjs/comments/8avfej/ ... )
Elias Platek
6

Po prostu możesz utworzyć funkcję w pliku js i wyeksportować ją do wykorzystania w komponentach

jak poniżej:

export default function setTitle(title) {
  if (typeof title !== "string") {
     throw new Error("Title should be an string");
  }
  document.title = title;
}

i użyj go w dowolnym komponencie takim jak ten:

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
amin msh
źródło
3

Możesz użyć następujących poniżej z 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')
);

lub Możesz użyć tego pakietu 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')
);

Miłego kodowania !!!

EsterlingAccime Youtuber
źródło
2

Nie testowałem tego zbyt dokładnie, ale wydaje się, że działa. Napisane w 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;
    }
}

Stosowanie:

export default class App extends React.Component<Props, State> {

    render() {
        return <>
            <DocumentTitle>{this.state.files.length} Gallery</DocumentTitle>
            <Container>
                Lorem ipsum
            </Container>
        </>
    }
}

Nie jestem pewien, dlaczego inni chętnie umieszczają całą swoją aplikację w swoim <Title>komponencie, to wydaje mi się dziwne.

Zaktualizując document.titlewnętrze render(), odświeży / będzie na bieżąco, jeśli chcesz dynamicznego tytułu. Powinien również przywrócić tytuł po odmontowaniu. Portale są urocze, ale wydają się niepotrzebne; tak naprawdę nie musimy tutaj manipulować żadnymi węzłami DOM.

mpen
źródło
2

Możesz użyć ReactDOM i zmienić <title>tag

ReactDOM.render(
   "New Title",
   document.getElementsByTagName("title")[0]
);
reza moradi
źródło
1

Od React 16.8. możesz zbudować niestandardowy hook, aby to zrobić (podobnie do rozwiązania @Shortchange):

export function useTitle(title) {
  useEffect(() => {
    const prevTitle = document.title
    document.title = title
    return () => {
      document.title = prevTitle
    }
  })
}

można go zastosować w dowolnym elemencie reakcyjnym, np .:

const MyComponent = () => {
  useTitle("New Title")
  return (
    <div>
     ...
    </div>
  )
}

Zaktualizuje tytuł, gdy tylko komponent zostanie zamontowany i przywróci poprzedni tytuł po odłączeniu.

Mistrz Bruce
źródło
0

Używam tej metody, o której się przekonałem, bo jest mi łatwiej. Używam go w połączeniu z komponentem funkcyjnym. Zrób to tylko wtedy, gdy nie obchodzi Cię, że nie wyświetli żadnego tytułu, jeśli użytkownik wyłączy Javascript na Twojej stronie.

Musisz zrobić dwie rzeczy.

1. Przejdź do swojego index.html i usuń ten wiersz tutaj

<title>React App</title>

2.Przejdź do funkcji aplikacji głównej i zwróć to, co jest zwykłą strukturą HTML, możesz skopiować i wkleić główną treść ze swojej witryny między tagami body:

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

Możesz dowolnie zmieniać tytuł.

Makusium
źródło
0
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>;
}

To całkiem proste rozwiązanie, które zaproponowałem podczas dzisiejszej pracy. setTitlezwraca funkcję, która resetuje tytuł do tego, co było przed użyciem setTitle, działa wspaniale wewnątrz hooka Reacta useEffect.

Krótka zmiana
źródło
1
To jest właściwy sposób, aby to zrobić. Ale na pewno byłoby miło nie musieć. Koncepcja jest wystarczająco wielokrotnego użytku, aby po prostu być na npm.
Eugene Kuzmenko
-8

Jeśli jesteś początkującym, możesz po prostu uchronić się przed tym wszystkim, przechodząc do publicznego folderu swojego folderu projektu reagującego, edytuj tytuł w „index.html” i wstaw swój. Nie zapomnij zapisać, aby to odzwierciedlić.

Stanleynd
źródło