Есть ли способ изменить заголовок страницы с помощью React-Router v4 +? - PullRequest
0 голосов
/ 21 сентября 2018

Я ищу способ изменить заголовок страницы, когда React-Router v4 + меняет местоположение.Раньше я слушал действие по изменению местоположения в Redux и проверял этот маршрут по объекту metaData.

При использовании React-Router v4 + нет списка фиксированных маршрутов.Фактически, различные компоненты сайта могут использовать Route с одинаковой строкой пути.Это означает, что старый метод, который я использовал, больше не будет работать.

Есть ли способ обновить заголовок страницы, вызывая действия при изменении определенных основных маршрутов, или есть лучший способ обновить метаданные сайта?

Ответы [ 7 ]

0 голосов
/ 17 мая 2019

Вот мое решение, которое почти такое же, как простая установка document.title, но с использованием 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]
  );
}

Это имеет преимущество в том, что повторный рендеринг возможен только в том случае, если вы изменили deps.Никогда не перерисовывать:

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

Перерисовывать только если мои userId изменяются:

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 здесь, но не может обновить заголовок кадра

ЕслиВы проверяете <head> кадра, вы можете увидеть изменения: screenshot

0 голосов
/ 31 мая 2019

Используя функциональный компонент на главной странице маршрутизации, вы можете изменять заголовок при каждом изменении маршрута с помощью useEffect .

Например,

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

    return (
      <Switch>
        <Route path='/a' />
        <Route path='/b' />
        <Route path='/c' />
      </Switch>
    );
}
0 голосов
/ 17 мая 2019

С небольшой помощью от Шлема:

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>
  )
}
0 голосов
/ 29 марта 2019

Я немного собрал решение Thierry Prosts и получил следующее:

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

И моя реализация маршрутизатора выглядела так:

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

Настройка частного маршрута:

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

Это позволило мне обновлять как публичные области с новым названием, так и частные области.

0 голосов
/ 29 марта 2019

В ответ на отличный ответ phen0menon, почему бы не расширить Route вместо React.Component?

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

, это удалит служебный код, как показано ниже:

// old:
<Route
  exact
  path="/"
  render={props => (
    <Page {...props} component={Index} title="Index Page" />
  )}
/>
// improvement:
<Route 
  exact
  path="/"
  component={Index}
  title="Index Page" />
0 голосов
/ 09 января 2019

<Route /> компоненты имеют свойство render .Таким образом, вы можете изменить заголовок страницы при изменении местоположения, объявив ваши маршруты следующим образом:

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

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

В Page компоненте вы можете установить название маршрута:

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

Обновление 1 августа 2019 .Это работает только с response-router> = 4.x.Благодаря @ supremebeing7

0 голосов
/ 21 сентября 2018

В вашем методе componentDidMount() сделайте это для каждой страницы

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

Это изменит заголовок вашей страницы, сделайте вышеупомянутое для каждого маршрута.

Также, если оно большетолько заглавная часть, отметьте реагирующий шлем Это очень аккуратная библиотека для этого, которая также обрабатывает некоторые замечательные случаи.

...