source

React-Router v4+로 페이지 제목을 변경할 수 있는 방법이 있습니까?

manysource 2023. 2. 22. 22:38

React-Router v4+로 페이지 제목을 변경할 수 있는 방법이 있습니까?

React-Router v4+가 위치를 변경할 때 페이지 제목을 변경하는 방법을 찾고 있습니다.Redx 로케이션 변경 액션을 듣고 그 루트를 체크하고metaData물건.

React-Router v4+를 사용하는 경우 고정 경로 목록은 없습니다.실제로 사이트 주변의 다양한 컴포넌트는Route같은 패스 스트링을 사용합니다.그 말은 내가 쓰던 방법이 더 이상 통하지 않는다는 거야.

주요 루트가 변경되었을 때 액션을 호출하여 페이지 제목을 갱신할 수 있는 방법이 있습니까?아니면 사이트의 메타데이터를 갱신할 수 있는 더 좋은 방법이 있습니까?

<Route />컴포넌트에는 렌더 속성이 있습니다.따라서 다음과 같이 루트를 선언함으로써 로케이션이 변경되었을 때 페이지 제목을 변경할 수 있습니다.

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

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

Pagecomponent는 루트 제목을 설정할 수 있습니다.

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

2019년 8월 1일 갱신.이것은 react-module > = 4.x에서만 작동합니다.@supremebing7 덕분에

리액트 훅을 사용하여 답변 업데이트:

다음 컴포넌트를 사용하여 임의의 경로의 제목을 지정할 수 있습니다.이 컴포넌트는 를 사용하여 구축됩니다.useEffect.

import { useEffect } from "react";

const Page = (props) => {
  useEffect(() => {
    document.title = props.title || "";
  }, [props.title]);
  return props.children;
};

export default Page;

그리고 나서Page에서render루트 프롭:

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

<Route
  path="/profile"
  render={(props) => (
    <Page title="Profile">
      <Profile {...props} />
    </Page>
  )}
/>

고객님의 고객명componentDidMount()방법 모든 페이지에 대해 이 작업을 수행합니다.

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

그러면 페이지 제목이 변경되어 모든 경로에 대해 위에서 언급한 작업을 수행합니다.

또한 제목 부분보다 더 많은 경우 react-helmet을 확인하십시오. 이 기능은 매우 깔끔한 라이브러리이며, 몇 가지 멋진 엣지 케이스도 처리합니다.

phen0menon의 훌륭한 답변에서 따온다면, 대신 확장해보는 것은 어떨까요?

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

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

이렇게 하면 다음과 같이 오버헤드 코드가 제거됩니다.

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

// improvement:
  <Page
    exact
    path="/"
    component={Index}
    title="Index Page"
  />

업데이트: 커스텀 훅을 사용하는 방법도 있습니다.

import { useEffect } from 'react';

/** Hook for changing title */
export const useTitle = title => {
  useEffect(() => {
    const oldTitle = document.title;
    title && (document.title = title);
    // following line is optional, but will reset title when component unmounts
    return () => document.title = oldTitle;
  }, [title]);
};

메인 라우팅 페이지의 기능 컴포넌트를 사용하면 useEffect를 사용하여 각 경로의 제목을 변경할 수 있습니다.

예를들면,

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

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

Tierry Prosts 솔루션을 기반으로 구축한 결과 다음과 같은 결과가 나왔습니다.

업데이트 2020년 1월: 구성 요소도 Typescript로 업데이트했습니다.

2021년 8월 업데이트: TypeScript에 개인 루트를 추가했습니다.

import React, { FunctionComponent, useEffect } from 'react';
import { Route, RouteProps } from 'react-router-dom';

interface IPageProps extends RouteProps {
  title: string;
}

const Page: FunctionComponent<IPageProps> = props => {
  useEffect(() => {
    document.title = "Website name | " + props.title;
  });

  const { title, ...rest } = props;
  return <Route {...rest} />;
};

export default Page;

업데이트: My Page.jsx 컴포넌트는 이제 기능 컴포넌트가 되었습니다.useEffect 훅이 있는 경우:

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

const Page = (props) => {
  useEffect(() => {    
    document.title = "Website name | " + props.title;
  });

  const { title, ...rest } = props;
  return <Route {...rest} />;
}

export default Page;

아래에는 초기 솔루션이 나와 있습니다.

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

TypeScript의 개인 경로:

export const PrivateRoute = ({ Component, ...rest }: IRouteProps): JSX.Element => {
  return (
    <Page
      {...rest}
      render={(props) =>
        userIsAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: Paths.login,
              state: { from: props.location },
            }}
          />
        )
      }
    />
  );
};

이를 통해 퍼블릭 영역 모두 새로운 제목으로 업데이트하고 프라이빗 영역도 업데이트할 수 있게 되었습니다.

헬멧의 약간의 도움을 받아:

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

설정이나 마찬가지의 .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 re never. 다시렌더링하지 않음다음과 같이 합니다.

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>변경 내용을 확인할 수 있습니다.

컴포넌트 내의 반복을 피하기 위해 한 단계 더 나아가서 제목을 한 곳(라우터 모듈)에서 갱신할 수 있다고 생각하기 때문에 이 답변을 드렸습니다.

평소에는 루트를 어레이로 선언하고 있습니다만, 스타일에 따라 실장을 변경할 수 있습니다.기본적으로 이런 ==>

import {useLocation} from "react-router-dom";
const allRoutes = [
  {
        path: "/talkers",
        component: <Talkers />,
        type: "welcome",
        exact: true,
    },
    {
        path: "/signup",
        component: <SignupPage />,
        type: "onboarding",
        exact: true,
    },
  ]

const appRouter = () => {
    const theLocation = useLocation();
    const currentLocation = theLocation.pathname.split("/")[1];
    React.useEffect(() => {
        document.title = `<Website Name> | 
        ${currentLocation[0].toUpperCase()}${currentLocation.slice(1,)}`
    }, [currentLocation])

   return (
     <Switch>
      {allRoutes.map((route, index) => 
        <Route key={route.key} path={route.path} exact={route.exact} />}
    </Switch>

   )

}

또 은 '다 하다'라는에 이미 '다'가 있다고 입니다.allRoutes@Denis Skiba @Denis Skiba @Denis Skiba 。

'다, 하다, 하다'로 갈 수도 있어요.render

const routes = [
 {
   path: "/main",
   component: MainPage,
   title: "Main Page",
   exact: true
 },
 {
   path: "/about",
   component: AboutPage,
   title: "About Page"
 },
 {
   path: "/titlessPage",
   component: TitlessPage
 }
];

const Routes = props => {
 return routes.map((route, idx) => {
   const { path, exact, component, title } = route;
   return (
     <Route
       path={path}
       exact={exact}
       render={() => {
         document.title = title ? title : "Unknown title";
         console.log(document.title);
         return route.component;
       }}
     />
   );
 });
};

codesandbox 예제(제목 참조에 대한 새 창이 열립니다)

리액트 헬메트를 사용해 주세요.Typescript의 예를 들어보겠습니다.

import { Helmet } from 'react-helmet';

const Component1Title = 'All possible elements of the <head> can be changed using Helmet!';
const Component1Description = 'No only title, description etc. too!';

class Component1 extends React.Component<Component1Props, Component1State> {
  render () {
    return (
      <>
        <Helmet>
          <title>{ Component1Title }</title>
          <meta name="description" content={Component1Description} />

        </Helmet>
        ...
      </>
    )
  }
}

상세: https://github.com/nfl/react-helmet#readme

Dan Abramov(Redux의 크리에이터이자 현재 React 팀의 멤버)는 제목을 설정하기 위한 컴포넌트를 만들었습니다.이 컴포넌트는 React Router의 새로운 버전에서도 사용할 수 있습니다.매우 사용하기 쉽고 자세한 내용은 여기를 참조하십시오.

https://github.com/gaearon/react-document-title

예:

<DocumentTitle title='My Web App'>

언급URL : https://stackoverflow.com/questions/52447828/is-there-a-way-to-modify-the-page-title-with-react-router-v4