web-dev-qa-db-de.com

Gibt es eine Möglichkeit, den Seitentitel mit React-Router v4 + zu ändern?

Ich suche nach einer Möglichkeit, den Seitentitel zu ändern, wenn React-Router v4 + den Speicherort ändert. Ich habe in Redux auf eine Standortänderungsaktion gewartet und diese Route mit einem metaData -Objekt verglichen.

Bei Verwendung von React-Router v4 + gibt es keine Liste fester Routen. Tatsächlich könnten verschiedene Komponenten auf der Site Route mit derselben Pfadzeichenfolge verwenden. Das bedeutet, dass die alte Methode, die ich verwendet habe, nicht mehr funktioniert.

Gibt es eine Möglichkeit, den Seitentitel durch Aufrufen von Aktionen zu aktualisieren, wenn bestimmte Hauptrouten geändert werden, oder gibt es eine bessere Methode zum Aktualisieren der Metadaten der Site?

18
Sawtaytoes

Führen Sie dies in Ihrer componentDidMount() -Methode für jede Seite aus

componentDidMount() {
  document.title = 'Your page title here';
}

Dies ändert Ihren Seitentitel. Führen Sie die oben genannten Schritte für jede Route aus.

Auch wenn es mehr als nur der Titelteil ist, überprüfen Sie Reaktionshelm Dies ist eine sehr übersichtliche Bibliothek und behandelt auch einige Nice Edge-Fälle.

20
Adeel Imran

<Route /> Komponenten haben die Eigenschaft Rendern . So können Sie den Seitentitel ändern, wenn sich der Standort ändert, indem Sie Ihre Routen folgendermaßen deklarieren:

<Route
  exact
  path="/"
  render={props => (
    <Page {...props} component={Index} title="Index Page" />
  )}
/>

<Route
  path="/about"
  render={props => (
    <Page {...props} component={About} title="About Page" />
  )}
/>

In der Komponente Page können Sie den Routentitel festlegen:

import React from "react"

/* 
 * Component which serves the purpose of a "root route component". 
 */
class Page extends React.Component {
  /**
   * Here, we define a react lifecycle method that gets executed each time 
   * our component is mounted to the DOM, which is exactly what we want in this case
   */
  componentDidMount() {
    document.title = this.props.title
  }

  /**
   * Here, we use a component prop to render 
   * a component, as specified in route configuration
   */
  render() {
    const PageComponent = this.props.component

    return (
      <PageComponent />
    )
  }
}

export default Page

Update 1. August 2019 . Dies funktioniert nur mit React-Router> = 4.x. Vielen Dank an @ supremebeing7

26
phen0menon

Wenn Sie eine Funktionskomponente auf Ihrer Hauptrouting-Seite verwenden, können Sie den Titel bei jeder Routenänderung mit seEffect ändern.

Beispielsweise,

const Routes = () => {
    useEffect(() => {
      let title = history.location.pathname
      document.title = title;
    });

    return (
      <Switch>
        <Route path='/a' />
        <Route path='/b' />
        <Route path='/c' />
      </Switch>
    );
}
3
Jordan Daniels

Hier ist meine Lösung, die fast gleichbedeutend ist mit dem einfachen Einstellen von document.title aber mit useEffect

/**
* Update the document title with provided string
 * @param titleOrFn can be a String or a function.
 * @param deps? if provided, the title will be updated when one of these values changes
 */
function useTitle(titleOrFn, ...deps) {
  useEffect(
    () => {
      document.title = isFunction(titleOrFn) ? titleOrFn() : titleOrFn;
    },
    [...deps]
  );
}

Dies hat den Vorteil, dass nur dann erneut gerendert wird, wenn Sie die von Ihnen angegebene deps -Änderung vornehmen. Nie wieder rendern:

const Home = () => {
  useTitle('Home');
  return (
    <div>
      <h1>Home</h1>
      <p>This is the Home Page</p> 
    </div>
  );
}

Rendern Sie nur, wenn sich mein userId ändert:

const UserProfile = ({ match }) => {
  const userId = match.params.userId;
  useTitle(() => `Profile of ${userId}`, [userId]);
  return (
    <div>
      <h1>User page</h1>
      <p>
        This is the user page of user <span>{userId}</span>
      </p>
    </div>
  );
};

// ... in route definitions
<Route path="/user/:userId" component={UserProfile} />
// ...

CodePen hier, kann aber den Rahmentitel nicht aktualisieren

Wenn Sie das <head> des Rahmens können Sie die Änderung sehen: screenshot

2
TecHunter

Mit ein bisschen Hilfe von Helmet:

import React from 'react'
import Helmet from 'react-helmet'
import { Route, BrowserRouter, Switch } from 'react-router-dom'

function RouteWithTitle({ title, ...props }) {
  return (
    <>
      <Helmet>
        <title>{title}</title>
      </Helmet>
      <Route {...props} />
    </>
  )
}

export default function Routing() {
  return (
    <BrowserRouter>
      <Switch>
        <RouteWithTitle title="Hello world" exact={true} path="/" component={Home} />
      </Switch>
    </BrowserRouter>
  )
}
1
Fellow Stranger

Warum nicht Route anstelle von React.Component erweitern?

import React, { useEffect } from 'react';
import { Route } from 'react-router-dom';
import PropTypes from 'prop-types';

const Page = ({ title, ...rest }) => {
  useEffect(() => {
    document.title = title), []
  };
  return <Route {...rest} />;
};

Page.propTypes = {
  title: PropTypes.string.isRequired,
};

export { Page };

dadurch wird der Overhead-Code wie folgt entfernt:

// old:
<Route
  exact
  path="/"
  render={props => (
    <Page {...props} component={Index} title="Index Page" />
  )}
/>
// improvement:
<Page 
  exact
  path="/"
  component={Index}
  title="Index Page" />
1
Thierry Prost

Ich habe ein bisschen auf der Thierry Prosts-Lösung aufgebaut und bin zu folgendem Ergebnis gekommen:

// Page.jsx
import React from 'react';
import { Route } from 'react-router-dom';

class Page extends Route {
  componentDidMount() {
    document.title = "Website name | " + this.props.title;
  }

  componentDidUpdate() {      
      document.title = "Website name | " + this.props.title;
  }

  render() {
    const { title, ...rest } = this.props;
    return <Route {...rest} />;
  }
}

export default Page;

Und meine Router-Implementierung sah so aus:

// App.js / Index.js
<Router>
    <App>
      <Switch>
         <Page path="/" component={Index} title="Index" />
         <PrivateRoute path="/secure" component={SecurePage} title="Secure" />
      </Switch>
    </App>    
  </Router>

Private Route einrichten:

// PrivateRoute
function PrivateRoute({ component: Component, ...rest }) {
  return (
    <Page
      {...rest}
      render={props =>
        isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/",
              state: { from: props.location }
            }}
          />
        )
      }
    />
  );
}

Dadurch konnte ich sowohl die öffentlichen Bereiche mit einem neuen Titel als auch die privaten Bereiche aktualisieren.

1
Hsjakobsen