반응 라우터를 사용하여 프로그래밍 방식으로 탐색


1427

와 react-router내가 사용할 수 있습니다 Link기본적으로 처리 라우터 반응하는 링크를 생성하는 요소.

내부적으로 호출하는 것을 봅니다 this.context.transitionTo(...).

탐색을하고 싶습니다. 링크가 아니라 드롭 다운 선택 (예 :)입니다. 코드에서 어떻게 할 수 있습니까? 무엇입니까 this.context?

나는 Navigationmixin을 보았지만없이 이것을 할 수 mixins있습니까?


26
이 질문에 반응 라우터의 주요 릴리스, 반작용의 주요 릴리스, 그리고 자바 스크립트의 주요 릴리스에 걸쳐 것을 명심 @SergioTapia
— 조지 마우어

5
다음은 react router v4의 공식 문서에있는 튜토리얼 링크입니다. reacttraining.com/react-router/web/guides/scroll-restoration
— chitzui

4
이 응답 확인할 수 있습니다 stackoverflow.com/questions/44127739/...
— 하기 Shubham 카트리

4
이 답변에 대해 기뻐하지만,이게 복잡해서 슬프다. 웹앱 내에서 탐색하는 것은 쉽고 잘 문서화되어야합니다. VueJS는 사소한 일입니다. 각 구성 요소는 라우터 인스턴스가 자동으로 주입됩니다. 문서에는 명확하게 정의 된 섹션이 있습니다. router.vuejs.org/guide/essentials/navigation.html 많은 것들에 대해 React를 좋아하지만 때로는 너무 복잡합니다. </ rant>
— colefner

7
@GeorgeMauer 당신이 맞아요. 그것이이 커뮤니티의 문제가 아닙니다. 프레임 워크에 대한 문제가 아니라 질문에 대한 답변입니다. 알림 주셔서 감사합니다.
— colefner

답변:


1428

후크가있는 React Router v5.1.0

useHistoryReact> 16.8.0 및 기능적 구성 요소를 사용하는 경우 React Router> 5.1.0에 새로운 후크가 있습니다.

import { useHistory } from "react-router-dom";

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

라우터 v4 반응

React Router v4를 사용하면 구성 요소 내에서 프로그래밍 방식으로 라우팅 할 수있는 세 가지 방법이 있습니다.

  1. withRouter고차 부품을 사용하십시오 .
  2. 컴포지션 사용 및 렌더링 <Route>
  3. 를 사용하십시오 context.

React Router는 대부분 history라이브러리를 둘러싼 래퍼 입니다. 브라우저 및 해시 기록을 통해 브라우저와 history의 상호 작용을 처리합니다 window.history. 또한 전역 기록이없는 환경에 유용한 메모리 기록을 제공합니다. 이는 특히 모바일 앱 개발 ( react-native) 및 노드를 사용한 단위 테스트에 유용합니다 .

history인스턴스를 탐색하기위한 두 가지 방법이 있습니다 : push와 replace. history를 방문한 위치의 배열로 생각 하면 배열에 push새 위치를 추가하고 배열 replace의 현재 위치를 새 위치로 바꿉니다. 일반적으로 push탐색 할 때이 방법 을 사용하려고합니다 .

이전 버전의 React Router에서는 자체 history인스턴스 를 작성해야 했지만 v4 <BrowserRouter>에서는 <HashRouter>, 및 <MemoryRouter>구성 요소가 브라우저, 해시 및 메모리 인스턴스를 작성합니다. React Router는 라우터와 history연결된 인스턴스 의 속성과 메서드를 컨텍스트 아래의 router개체 아래에서 사용할 수있게 합니다.

1. withRouter고차 부품 사용

withRouter고차 성분을 분사 할 history컴포넌트의 소품으로 개체. 이를 통해 를 처리하지 않고도 push및 replace메소드 에 액세스 할 수 있습니다 context.

import { withRouter } from 'react-router-dom'
// this also works with react-router-native

const Button = withRouter(({ history }) => (
  <button
    type='button'
    onClick={() => { history.push('/new-location') }}
  >
    Click Me!
  </button>
))

2. 컴포지션을 사용하고 <Route>

<Route>구성 요소는 일치하는 위치는 아니다. 경로없는 경로를 렌더링 할 수 있으며 항상 현재 위치와 일치합니다 . <Route>구성 요소와 같은 소품을 통과 withRouter당신이 액세스 할 수 있도록 history관통 방법을 history소품.

import { Route } from 'react-router-dom'

const Button = () => (
  <Route render={({ history}) => (
    <button
      type='button'
      onClick={() => { history.push('/new-location') }}
    >
      Click Me!
    </button>
  )} />
)

3. 문맥을 사용하십시오 *

그러나 당신은 아마해서는 안됩니다

마지막 옵션은 React의 컨텍스트 모델로 편안하게 작업 할 수있는 경우에만 사용해야하는 옵션입니다 (React의 컨텍스트 API는 v16부터 안정적 ​​임).

const Button = (props, context) => (
  <button
    type='button'
    onClick={() => {
      // context.history.push === history.push
      context.history.push('/new-location')
    }}
  >
    Click Me!
  </button>
)

// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  })
}

1과 2는 구현하기에 가장 간단한 선택이므로 대부분의 경우 가장 좋은 선택입니다.


24
나는 이런 식으로 방법 1을 RoRo (({history}) => {console.log ( "hhhhhhhh"); history.push ( '/ bets')}); 그러나 라우터 4에서는 작동하지 않았습니다.
— Dmitry Malugin 14:07에

57
뭐!? 모든 구성 요소 withRouter를 통과 하는 대신 사용할 수 history있습니까 ?? Gahh 나는 문서를 읽는 데 더 많은 시간을 할애해야한다 ...
— hellojeffhall

18
history.push('/new-location')해당 동작을 Button 또는 다른 DOM 요소에 연결하지 않고 어떻게 실행할 수 있습니까?
— 닐

4
같은 오류를 던지는Unexpected use of 'history' no-restricted-globals
— Pardeep 자이나교

18
context반응 16 현재 더 이상 실험되지 않습니다.
— trysis

920

React-Router 5.1.0+ 답변 (후크 사용 및 React> 16.8)

useHistory기능 구성 요소 의 새로운 후크를 사용 하고 프로그래밍 방식으로 탐색 할 수 있습니다.

import { useHistory } from "react-router-dom";

function HomeButton() {
  let history = useHistory();
  // use history.push('/some/path') here
};

반응 라우터 4.0.0+ 답변

4.0 이상에서는 히스토리를 컴포넌트의 소품으로 사용하십시오.

class Example extends React.Component {
   // use `this.props.history.push('/some/path')` here
};

참고 :이 컴포넌트가에 의해 렌더링되지 않은 경우 this.props.history는 존재하지 않습니다 <Route>. <Route path="..." component={YourComponent}/>YourComponent에 this.props.history가 있어야합니다.

반응 라우터 3.0.0+ 답변

3.0 이상에서는 라우터를 컴포넌트의 소품으로 사용하십시오.

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

반응 라우터 2.4.0+ 답변

2.4 이상에서는 상위 구성 요소를 사용하여 라우터를 구성 요소의 소품으로 가져옵니다.

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
var DecoratedExample = withRouter(Example);

// PropTypes
Example.propTypes = {
  router: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  }).isRequired
};

반응 라우터 2.0.0+ 답변

이 버전은 1.x와 역 호환되므로 업그레이드 안내서가 필요하지 않습니다. 예제를 살펴 보는 것만으로도 충분합니다.

즉, 새로운 패턴으로 전환하려면 라우터 내부에 액세스 할 수있는 browserHistory 모듈이 있습니다.

import { browserHistory } from 'react-router'

이제 브라우저 기록에 액세스 할 수 있으므로 밀어 넣기, 바꾸기 등의 작업을 수행 할 수 있습니다.

browserHistory.push('/some/path')

추가 자료 : 기록 및 탐색


반응 라우터 1.xx 답변

나는 세부 사항을 업그레이드하지 않을 것입니다. 업그레이드 안내서 에서 이에 대해 읽을 수 있습니다

여기서 질문에 대한 주요 변경 사항은 탐색 믹스 인에서 기록으로 변경되었습니다. 이제 브라우저 historyAPI를 사용하여 경로를 변경하므로 앞으로 사용할 것 pushState()입니다.

다음은 Mixin을 사용하는 예입니다.

var Example = React.createClass({
  mixins: [ History ],
  navigateToHelpPage () {
    this.history.pushState(null, `/help`);
  }
})

이주의 History에서 온다 rackt / 역사 프로젝트. React-Router 자체가 아닙니다.

ES6 클래스로 인해 어떤 이유로 Mixin을 사용하지 않으려면 라우터에서 가져온 기록에 액세스 할 수 있습니다 this.props.history. 라우터에서 렌더링 한 구성 요소에만 액세스 할 수 있습니다. 따라서 하위 구성 요소에서 사용하려면를 통해 속성으로 전달해야합니다 props.

1.0.x 설명서 에서 새 릴리스에 대한 자세한 내용을 읽을 수 있습니다

컴포넌트 외부 탐색에 대한 도움말 페이지 는 다음과 같습니다.

참조를 잡고 history = createHistory()호출 하는 것이 좋습니다 replaceState.

반응 라우터 0.13.x 답변

나는 같은 문제에 봉착했고 반응 라우터와 함께 제공되는 Navigation 믹스 인 솔루션 만 찾을 수있었습니다.

내가 한 방법은 다음과 같습니다

import React from 'react';
import {Navigation} from 'react-router';

let Authentication = React.createClass({
  mixins: [Navigation],

  handleClick(e) {
    e.preventDefault();

    this.transitionTo('/');
  },

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

transitionTo()액세스 할 필요없이 전화를 걸 수있었습니다.context

아니면 당신은 멋진 ES6를 시도 할 수 있습니다 class

import React from 'react';

export default class Authentication extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();

    this.context.router.transitionTo('/');
  }

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
}

Authentication.contextTypes = {
  router: React.PropTypes.func.isRequired
};

반응 라우터 루덕

참고 : Redux 를 사용하는 경우 React-Redux 와 동일한 접근 방식을 사용하여 ReactRouter에 대한 redux 바인딩을 제공하는 React-Router-Redux 라는 또 다른 프로젝트 가 있습니다.

React-Router-Redux에는 액션 제작자 내부를 간단하게 탐색 할 수있는 몇 가지 방법이 있습니다. 이는 React Native에 기존 아키텍처가있는 사람들에게 특히 유용 할 수 있으며, 보일러 플레이트 오버 헤드를 최소화하면서 React Web에서 동일한 패턴을 활용하고자합니다.

다음 방법을 탐색하십시오.

  • push(location)
  • replace(location)
  • go(number)
  • goBack()
  • goForward()

다음은 Redux-Thunk 사용 예입니다 .

./actioncreators.js

import { goBack } from 'react-router-redux'

export const onBackPress = () => (dispatch) => dispatch(goBack())

./viewcomponent.js

<button
  disabled={submitting}
  className="cancel_button"
  onClick={(e) => {
    e.preventDefault()
    this.props.onBackPress()
  }}
>
  CANCEL
</button>

3
나는 사용하고 v2.4.0있지만 언급 된 접근법이 나를 위해 작동하지 않는다. 내 앱이 전혀 렌더링되지 않고 콘솔 출력 : Uncaught TypeError: (0 , _reactRouter.withRouter) is not a function여기 내 SO 게시물 링크 : stackoverflow.com/questions/37306166/…
— nburk

7
이것은 받아 들일만한 대답이어야하며, 받아 들인 대답은 약간 혼란스럽고 매우 오래되었습니다. @GiantElk 나는 버전에 대한 답변에서 설명한대로 작동 2.6.0합니다.
— JMac

2
이 방법은 여전히 ​​버전에 권장되는 방법 3.0.x입니까? 많은 사람들이 그 context길 을 이용하는 것 같습니다 .
— velop

6
4.0에서는 this.props.history가 존재하지 않습니다. 무슨 일이야?
— Nicolas S.Xu

4
this.props.history구성 요소가에 의해 렌더링되지 않은 경우 @ NicolasS.Xu 가 존재하지 않습니다 <Route>. 당신은 사용해야 <Route path="..." component={YourComponent}/>가지고 this.props.history에서 YourComponent.
— vogdb

508

반응 라우터 v2

가장 최근 릴리스 ( v2.0.0-rc5)의 경우 권장 탐색 방법은 기록 싱글 톤을 직접 푸시하는 것입니다. 구성 요소 외부 탐색 문서 에서 실제로 작동하는 것을 볼 수 있습니다 .

관련 발췌 :

import { browserHistory } from 'react-router';
browserHistory.push('/some/path');

최신 반응 라우터 API를 사용하는 경우 컴포넌트 내부 history에서 from 을 사용해야합니다 this.props.

this.props.history.push('/some/path');

또한 제공 pushState하지만 기록 된 경고에 따라 더 이상 사용되지 않습니다.

를 사용 react-router-redux하면 다음 push과 같이 전달할 수 있는 기능을 제공합니다 .

import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));

그러나 이것은 실제로 페이지를 탐색하지 않고 URL을 변경하는 데만 사용될 수 있습니다.


15
최신 API는 사용 import { browserHistory } from './react-router'하지 않고 대신를 사용하여 기록을 생성 한다는 것을 잊지 마십시오 import createBrowserHistory from 'history/lib/createBrowserHistory'. 나중에 history컴포넌트 소품에서 액세스 할 수 있습니다 .this.props.history('/some/path')
— Ricardo Pedroni

7
var browserHistory = require('react-router').browserHistory; browserHistory.goBack();
— Bobby

7
react-router-redux push는 URL 만 변경하고 실제로 페이지는 변경하지 않습니다. , 수입 모두를 수행 browserHistory에서 react-router사용을 browserHistory.push('/my-cool-path'). 불행히도, 이것은 찾기가 쉽지 않습니다. github.com/reactjs/react-router/blob/master/docs/guides/…
— Andrew Samuelsen

4
this.props.history.push ( '/')를 사용하고 있지만 URL 만 변경됩니다 ... 실제 라우팅은 없습니다. 내가 무엇을 놓치고 있습니까?
— rgcalsaverini 2016 년


56

ES6을 사용 react-router v2.0.0하여 이를 수행하는 방법은 다음과 같습니다 . 믹스 인에서 멀어졌습니다.react-router

import React from 'react';

export default class MyComponent extends React.Component {
  navigateToPage = () => {
    this.context.router.push('/my-route')
  };

  render() {
    return (
      <button onClick={this.navigateToPage}>Go!</button>
    );
  }
}

MyComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}

5
현재 권장 사항은 history@Bobby가 언급 한대로 싱글 톤 을 사용하는 것입니다. 당신은 할 수 사용 context.router하지만 인스턴스로 단위 테스트에 정말 어려운 그 구성 요소를 만들고있어 단지 구성 요소가 맥락에서이 문제가 발생하지 않습니다.
— George Mauer

2
@ GeorgeMauer 코드가 실행되는 위치에 달려 있다고 생각합니다. 반응 문서에 따라 서버에서 실행되는 context.router 사용법이 권장됩니다. github.com/reactjs/react-router/blob/master/upgrade-guides/…
— KumarM

50

반응 라우터 4.x 답변 :

결국에는 구성 요소 외부에서도 수행 할 수있는 단일 기록 개체를 갖고 싶습니다. 내가 좋아하는 것은 주문형으로 가져 와서 조작하는 하나의 history.js 파일을 갖는 것입니다.

BrowserRouter라우터 로 변경 하고 히스토리 소품을 지정하기 만하면 됩니다. 원하는대로 조작 할 수있는 고유 한 히스토리 오브젝트가 있다는 점을 제외하고는 아무것도 변경되지 않습니다.

에 의해 사용되는 라이브러리 인 history 를 설치해야합니다 react-router.

사용법 예, ES6 표기법 :

history.js

import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()

BasicComponent.js

import React, { Component } from 'react';
import history from './history';

class BasicComponent extends Component {

    goToIndex(e){
        e.preventDefault();
        history.push('/');
    }

    render(){
        return <a href="#" onClick={this.goToIndex}>Previous</a>;
    }
}

2018 년 4 월 16 일 수정 :

실제로 Route컴포넌트 에서 렌더링 된 컴포넌트를 탐색해야하는 경우 다음 과 같이 소품에서 히스토리에 액세스 할 수도 있습니다.

BasicComponent.js

import React, { Component } from 'react';

class BasicComponent extends Component {

    navigate(e){
        e.preventDefault();
        this.props.history.push('/url');
    }

    render(){
        return <a href="#" onClick={this.navigate}>Previous</a>;
    }
}

2
React Router 문서를 제외하고는 대부분의 경우 Router대신 대신 사용할 필요가 없다고 말합니다 BrowserRouter. 개체를 BrowserRouter만들고 유지 관리합니다 history. [ "Redux와 같은 상태 관리 도구와의 긴밀한 통합이 필요합니다"] reacttraining.com/react-router/web/api/Router
— bobbyz

2
그것은 시간과 경험을 통해 배운 것입니다. 일반적으로 default를 사용하는 것이 좋은 습관 this.props.history이지만, 컴포넌트가 아닌 클래스에서 또는 React 컴포넌트로 빌드되지 않은 다른 도구에서 클래스를 수행하는 데 도움이되는 솔루션을 아직 찾지 못했습니다. 소품을 전달할 수 있습니다. 의견 주셔서 감사합니다 :)
— Eric Martin

44

이 경우 서버 측을 제어하지 않고 해시 라우터 v2를 사용하는 사람은 다음과 같습니다.

당신의 장소 역사를 (예를 들어 app_history.js ES6) 별도의 파일로 :

import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });

export default appHistory;

그리고 어디서나 사용하십시오!

반응 라우터의 진입 점 (app.js ES6) :

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Redirect } from 'react-router'
import appHistory from './app_history'
...
const render((
  <Router history={appHistory}>
  ...
  </Router>
), document.querySelector('[data-role="app"]'));

모든 구성 요소 (ES6) 내 탐색 :

import appHistory from '../app_history'
...
ajaxLogin('/login', (err, data) => {
  if (err) {
    console.error(err); // login failed
  } else {
    // logged in
    appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
  }
})

1
감사. 어쩌면 뭔가 빠졌을 수도 있습니다. 이것은 상위 두 답변과 정확히 같지 않습니까?
— George Mauer

2
"해시"탐색을 사용하는 경우 "react-router"v2에서 추가 모듈 "history"(이상한 해시 쿼리를 피하려면)를 설치해야하고 browserHistory를 사용하는 대신 useRouterHistory (createHashHistory)를 사용해야합니다 ( {queryKey : false}). 이것이 내가 이것을 게시 한 주된 이유입니다. 해시 기록으로 탐색하는 방법을 보여주었습니다.
— Alexey Volodko

1
아, 그렇습니다. 더 이상 그 프로젝트에 참여하고 있지 않지만 선호하는 방법은 history지금 두 가지 방법 중 하나 를 사용하는 것입니다.
— George Mauer

4
왜이 답변이 최고가 아닌가? Context 또는 HOC 또는 이벤트 프로토 타입에 문제가있는 이유는 무엇입니까? 왜 히스토리를 가져 와서 원하는 곳 어디에서나 사용하지 않겠습니까? 그냥 트레이드 오프를 이해하려고
— storm_buster

@storm_buster 트레이드 오프가 없습니다. ES6 모듈이 있으므로 사용해야합니다! 이것은 도구를 사용하고 싶지 않은 것들조차도 도구를 사용하는 전형적인 쇼케이스입니다 (이 경우 반응).
— Capaj

40

라우터 V4 반응

tl : dr;

if (navigate) {
  return <Redirect to="/" push={true} />
}

간단하고 선언적인 답변은 다음 <Redirect to={URL} push={boolean} />과 함께 사용해야합니다 .setState()

push : boolean- true 인 경우 경로 재 지정은 현재 항목을 바꾸는 대신 새 항목을 내역으로 푸시합니다.


import { Redirect } from 'react-router'

class FooBar extends React.Component {
  state = {
    navigate: false
  }

  render() {
    const { navigate } = this.state

    // here is the important part
    if (navigate) {
      return <Redirect to="/" push={true} />
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^

    return (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}

여기에 전체 예제가 있습니다 . 자세한 내용은 여기를 참조 하십시오 .

추신. 이 예에서는 ES7 + Property Initializer 를 사용 하여 상태를 초기화합니다. 관심이 있으시면 여기도 보십시오 .


이것이 내가 찾은 최고의 답변입니다. withRouter다시로드중인 경로에서 이미 사용 하지 못했습니다. 우리의 경우에, 우리는 이미 경로에 있거나 다른 곳에서 선택적으로 setState(원인 return <Redirect>)해야했습니다 history.push().
— karmakaze

매우 영리합니다. 그리고 매우 간단합니다. Tks. 전체 줄의 클릭을 처리하기를 원했기 때문에 ReactRouterTable 내에서 사용했습니다. onRowClick에서 상태를 설정하는 데 사용됩니다. setState ({navigateTo : "/ path /"+ row.uuid});
— Lovato

이것은 방탄 답변입니다.
— Nitin Jadhav 2

31

경고 : 이 답변은 1.0 이전의 ReactRouter 버전에만 해당됩니다.

이 답변을 1.0.0-rc1 사용 사례로 업데이트합니다!

믹스 인 없이도 할 수 있습니다.

let Authentication = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  handleClick(e) {
    e.preventDefault();
    this.context.router.transitionTo('/');
  },
  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

컨텍스트가있는 단점은 contextTypes클래스에서 를 정의하지 않으면 액세스 할 수 없다는 것입니다 .

문맥이 무엇인지에 관해서는 소품과 같이 부모에서 자식으로 전달되는 객체이지만 매번 소품을 다시 선언하지 않고도 암시 적으로 전달됩니다. https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html을 참조 하십시오


26

뭔가 제대로 작동하기 전에 적어도 10 가지 방법을 시도했습니다!

@Felipe Skinner의 withRouter답변은 저에게 압도적이었습니다. 나는 새로운 "ExportedWithRouter"클래스 이름을 만들고 싶을 지 확신하지 못했습니다.

현재 React-Router 3.0.0과 ES6의 가장 간단하고 깨끗한 방법은 다음과 같습니다.

ES6가있는 React-Router 3.xx :

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
export default withRouter(Example);

또는 기본 클래스가 아닌 경우 다음과 같이 내보내십시오.

withRouter(Example);
export { Example };

3.xx에서 <Link>구성 요소 자체는을 사용 router.push하므로 다음 <Link to=과 같이 태그에 전달할 항목을 전달할 수 있습니다 .

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'

1
완전히 잘 작동합니다. 그러나 코드 200 OK대신 응답합니다 30x. 이 문제를 어떻게 해결할 수 있습니까?
— Muhammad Ateeq Azam

1
확실하지 않다. 이것은 외부 요청이 아니기 때문에 나에게 결코 나타나지 않았습니다. 페이지의 코드를 사용하여 페이지의 내용을 변경하는 브라우저 일뿐입니다. 원하는 경우 언제든지 수동 자바 스크립트 리디렉션을 수행 할 수 있습니다.
— 벤 휠러

1
@withRouter와 함께 클래스 데코레이터로도 사용할 수 있습니다 ... mobx와 잘 어울립니다
— Dan

21

프로그래밍 방식으로 탐색을 수행하려면 에있는 props.history 에 새 기록 을 푸시해야 합니다 . 이렇게하면 다음과 같은 작업이 가능합니다.component

//using ES6
import React from 'react';

class App extends React.Component {

  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick(e) {
    e.preventDefault()
    /* Look at here, you can add it here */
    this.props.history.push('/redirected');
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          Redirect!!!
        </button>
      </div>
    )
  }
}

export default App;

— Ash

19

ES6 + React 구성 요소의 경우 다음 솔루션이 효과적이었습니다.

나는 Felippe skinner를 따랐지만 나 같은 초보자를 돕기 위해 엔드 투 엔드 솔루션을 추가했습니다.

아래는 내가 사용한 버전입니다.

"반응 라우터": "^ 2.7.0"

"반응": "^ 15.3.1"

다음은 반응 라우터를 사용하여 프로그래밍 방식 탐색을 사용한 반응 구성 요소입니다.

import React from 'react';

class loginComp extends React.Component {
   constructor( context) {
    super(context);
    this.state = {
      uname: '',
      pwd: ''
    };
  }

  redirectToMainPage(){
        this.context.router.replace('/home');
  }

  render(){
    return <div>
           // skipping html code 
             <button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
    </div>;
  }
};

 loginComp.contextTypes = {
    router: React.PropTypes.object.isRequired
 }

 module.exports = loginComp;

아래는 내 라우터의 구성입니다.

 import { Router, Route, IndexRedirect, browserHistory } from 'react-router'

 render(<Router history={browserHistory}>
          <Route path='/' component={ParentComp}>
            <IndexRedirect to = "/login"/>
            <Route path='/login' component={LoginComp}/>
            <Route path='/home' component={HomeComp}/>
            <Route path='/repair' component={RepairJobComp} />
            <Route path='/service' component={ServiceJobComp} />
          </Route>
        </Router>, document.getElementById('root'));

19

최선의 방법은 아니지만 ... 반응 라우터 v4를 사용하여 다음 Typescript는 일부 아이디어를 줄 수 있습니다.

예를 들어 아래의 렌더링 된 구성 요소 LoginPage에서 router객체에 액세스 할 수 있으며 router.transitionTo('/homepage')탐색을 위해 호출 만합니다.

탐색 코드는에서 가져 왔습니다 .

"react-router": "^4.0.0-2", "react": "^15.3.1",

import Router from 'react-router/BrowserRouter';
import { History } from 'react-history/BrowserHistory';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();

interface MatchWithPropsInterface {
  component: typeof React.Component,
  router: Router,
  history: History,
  exactly?: any,
  pattern: string
}

class MatchWithProps extends React.Component<MatchWithPropsInterface,any> {
  render() {
    return(
      <Match {...this.props} render={(matchProps) => (
             React.createElement(this.props.component, this.props)

        )}
       />
    )
  }
}

ReactDOM.render(
    <Router>
      {({ router }) => (
        <div>
          <MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
          <Miss component={NotFoundView} />
        </div>
      )}
    </Router>,

   document.getElementById('app')
);


1
Router 및 browserHistory와 함께 사용하지 않는 이유는 무엇입니까?
— Erwin Mayer

1
@Erwin v4에서는 API가 다릅니다. 이 github.com/ReactTraining/react-router/issues/3847을 참조하십시오 .
— mcku

1
@mcku react-router v4 용 typescript dts 파일은 어디서 얻었습니까?
— jmathew

1
@jmathew react-router v4에 대한 타입 정의가 없습니다
— mcku

16

에서 반작용-라우터 V4 및 ES6

withRouter및 을 사용할 수 있습니다 this.props.history.push.

import {withRouter} from 'react-router-dom';

class Home extends Component {

    componentDidMount() {
        this.props.history.push('/redirect-to');
    }
}

export default withRouter(Home);

2
이미 몇 가지 다른 답변에서 언급했습니다 (상위 답변의 길이 포함)
— George Mauer

13

withRouter클래스 기반 구성 요소와 함께 사용하려면 다음과 같이 해보십시오. 내보내기 명령문을 변경하여 사용하십시오 withRouter.

import { withRouter } from 'react-router-dom'

class YourClass extends React.Component {
  yourFunction = () => {
    doSomeAsyncAction(() =>
      this.props.history.push('/other_location')
    )
  }

  render() {
    return (
      <div>
        <Form onSubmit={ this.yourFunction } />
      </div>
    )
  }
}

export default withRouter(YourClass);

11


José Antonio Postigo와 Ben Wheeler 의 이전 답변 을 기반으로 한
참신? Typescript 로 작성하고 데코레이터
사용 또는 정적 속성 / 필드

import * as React from "react";
import Component = React.Component;
import { withRouter } from "react-router";

export interface INavigatorProps {
    router?: ReactRouter.History.History;
}

/**
 * Note: goes great with mobx 
 * @inject("something") @withRouter @observer
 */
@withRouter
export class Navigator extends Component<INavigatorProps, {}>{
    navigate: (to: string) => void;
    constructor(props: INavigatorProps) {
        super(props);
        let self = this;
        this.navigate = (to) => self.props.router.push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

/**
 * Non decorated 
 */
export class Navigator2 extends Component<INavigatorProps, {}> {

    static contextTypes = {
        router: React.PropTypes.object.isRequired,
    };

    navigate: (to: string) => void;
    constructor(props: INavigatorProps, context: any) {
        super(props, context);
        let s = this;
        this.navigate = (to) =>
            s.context.router.push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

오늘 npm을 설치 한 상태로. "react-router": "^ 3.0.0"및
"@ types / react-router": "^ 2.0.41"


11

수평선에 React-Router v4를 사용하면 새로운 방법이 있습니다.

import { MemoryRouter, BrowserRouter } from 'react-router';

const navigator = global && global.navigator && global.navigator.userAgent;
const hasWindow = typeof window !== 'undefined';
const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
const Router = isBrowser ? BrowserRouter : MemoryRouter;

<Router location="/page-to-go-to"/>

react-lego 는 반응 라우터를 사용 / 업데이트하는 방법을 보여주는 예제 앱이며 앱을 탐색하는 기능 테스트의 예를 포함합니다.


5
라이프 사이클 후크 또는 redux와 같은 것을 탐색하는 방법이 궁금하지만 렌더링 기능에서 탐색하는 데 좋습니다.
— Ruben Martinez Jr.

11

반응 라우터 v4에서. 프로그래밍 방식으로 라우팅하려면이 두 가지 방법을 따릅니다.

1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")

두 번째

히스토리 스택에서 현재 항목을 바꿉니다.

소품의 역사를 얻으려면 구성 요소를 포장해야 할 수도 있습니다.

라우터


감사!! 최고의 답변
— Taha Farooqui

9

해시 또는 브라우저 기록을 사용하는 경우 할 수 있습니다

hashHistory.push('/login');
browserHistory.push('/login');

2
hashHistory.push, 정의되지 않은 속성 "push"를 읽을 수 없습니다. 어디서 가져 오나요?
— ArchNoob

"react-router"에서 {hashHistory} 가져 오기; 상단에서이 방법으로 가져올 수 있습니다.
— Zaman Afzal

redux saga 파일에서 코드 샘플을 사용하고 있는데 말한 것처럼 가져 와서 사용하지만 TypeError가 계속 발생합니다.
— ArchNoob

8

현재 React 버전 (15.3) this.props.history.push('/location');으로 나를 위해 일했지만 다음 경고가 표시되었습니다.

browser로 49주의 :이 라우터 반응] props.history및 context.history중단된다. 를 사용하십시오 context.router.

그리고 다음과 context.router같이 사용하여 해결했습니다 .

import React from 'react';

class MyComponent extends React.Component {

    constructor(props) {
        super(props);
        this.backPressed = this.backPressed.bind(this);
    }

    backPressed() {
        this.context.router.push('/back-location');
    }

    ...
}

MyComponent.contextTypes = {
    router: React.PropTypes.object.isRequired
};

export default MyComponent;

1
이것은 V4에서 작동합니다. 글쎄 ... 닫기 ... 실제로 this.context.router.history.push ( '/ back-location');
— velohomme

7

반응 라우터 V4

버전 4를 사용하는 경우 액션을 전달하면 모든 것이 작동하는 내 라이브러리 (Shameless plug)를 사용할 수 있습니다!

dispatch(navigateTo("/aboutUs"));

삼겹살


5

반응 라우터 v4에서 이것을 구현하는 데 문제가있는 사람들.

다음은 redux 액션에서 반응 앱을 탐색하는 효과적인 솔루션입니다.

history.js

import createHistory from 'history/createBrowserHistory'

export default createHistory()

App.js / Route.jsx

import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
 <Route path="/test" component={Test}/>
</Router>

another_file.js 또는 redux 파일

import history from './history' 

history.push('/test') // this should change the url and re-render Test component

이 의견에 감사드립니다 : ReactTraining 문제 의견


4

react-router- redux를 통해 redux와 함께 RR4를 페어링 하는 경우 라우팅 작업 작성자를 사용하는 react-router-redux것도 옵션입니다.

import { push, replace, ... } from 'react-router-redux'

class WrappedComponent extends React.Component {
  handleRedirect(url, replaceState = true) { 
    replaceState 
      ? this.props.dispatch(replace(url)) 
      : this.props.dispatch(push(url)) 
  }
  render() { ... }
}

export default connect(null)(WrappedComponent)

redux thunk / saga를 사용하여 비동기 플로우를 관리하는 경우 위의 조치 작성자를 redux 조치로 가져오고 mapDispatchToProps를 사용하여 구성 요소에 반응하도록 연결하십시오.


1
react-router-redux오랜 시간 동안 보관 / 사용되지 않습니다
— oligofren

4

useHistory상태 비 저장 구성 요소에서 후크를 사용할 수도 있습니다 . 문서의 예.

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

  return (
    <button type="button" onClick={() => history.push("/home")}>
      Go home
    </button>
  )
}

참고 : 후크에 추가되었습니다 react-router@5.1.0및 필요react@>=16.8


1
좋은 전화, 당신은 어떤 버전의 반응 라우터와 반응을 언급하는지 알 수 있습니까? 항상 사용할 수 없었던 새로운 변경 사항입니다.
— George Mauer

3

정답은 글을 쓰는 시점에 나에게 있었다

this.context.router.history.push('/');

하지만 컴포넌트에 PropType을 추가해야합니다

Header.contextTypes = {
  router: PropTypes.object.isRequired
}
export default Header;

PropTypes를 가져 오는 것을 잊지 마십시오

import PropTypes from 'prop-types';

반응 라우터의 버전을 적어두고 반응 라우터에서 무엇을 가져
— Ash

가져올 내용이 없으며 버전 "react-router": "^ 4.2.0"
— 웹 마스터

3

아마도 가장 좋은 해결책은 아니지만 작업을 완료합니다.

import { Link } from 'react-router-dom';

// create functional component Post
export default Post = () => (
    <div className="component post">

        <button className="button delete-post" onClick={() => {
            // ... delete post
            // then redirect, without page reload, by triggering a hidden Link
            document.querySelector('.trigger.go-home').click();
        }}>Delete Post</button>

        <Link to="/" className="trigger go-home hidden"></Link>

    </div>
);

기본적으로 하나의 작업 (이 경우 사후 삭제)에 연결된 논리는 리디렉션을위한 트리거를 호출하게됩니다. 이는 마크 업에 DOM 노드 '트리거'를 추가하여 필요할 때 편리하게 호출 할 수 있기 때문에 이상적이지 않습니다. 또한 React 컴포넌트에서 원하지 않는 DOM과 직접 상호 작용합니다.

그러나 이러한 유형의 리디렉션은 종종 필요하지 않습니다. 따라서 구성 요소 마크 업에있는 하나 또는 두 개의 추가 숨겨진 링크는 특히 의미있는 이름을 지정하면 크게 손상되지 않습니다.


허용 된 솔루션보다 왜 이것을 사용하는지 설명 할 수 있습니까?
— George Mauer

논의 된 문제에 대한 대안 솔루션 일뿐입니다. 이미 언급했듯이 이상적인 것은 아니지만 프로그래밍 방식의 리디렉션에만 적합합니다.
— neatsu

2

이것은 특별한 수입품이 필요하지 않은 저에게 효과적이었습니다.

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>

물론 이것은 특별한 수입이 필요합니다-구성 요소가 그 자체로 history추가 되지 않았습니다 props. 사용하기 위해 가져와야 할 HoC에서 나온 것입니다. 직접 보낸 컴포넌트는 Route해당 HoC에 의해 자동으로 래핑되지만 가져 오기가 필요합니다 Route.
— George Mauer

2

대신 반응 라우터의 현대적인 대안 인 후크 라우터를 사용하십시오.

https://www.npmjs.com/package/hookrouter

import { useRoutes, usePath, A} from "hookrouter";

선택 상자를 통한 연결에 대한 OP 질문에 대답하려면 다음을 수행하십시오.

navigate('/about');

참고로 저자 자신은이 라이브러리를 "개념 증명"이라고 부르며 거의 1 년 동안 활동하지 않았습니다 (2019 년 6 월).
— MEMark

@MEMark 그것은 이미 완벽하기 때문입니다
— StefanBob

글쎄, 38 개의 공개 된 이슈는 버전 2.0이 저자에 따라 완전히 다시 작성 될 것이라는 사실과 함께 그렇지 않다고 말한다.
— MEMark

1

React Router v4 +의 경우

초기 렌더 자체 ( <Redirect>구성 요소 를 사용할 수 있음) 중에 탐색 할 필요가 없다고 가정하면 이것이 앱에서 수행하는 작업입니다.

null을 반환하는 빈 경로를 정의하면 기록 개체에 액세스 할 수 있습니다. Router정의 된 최상위 레벨에서이 작업을 수행해야합니다 .

지금 당신은에서 할 수있는 모든 것을 할 수있는 역사 처럼 history.push(), history.replace(), history.go(-1)등!

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

let routeHistory = null;

export function navigateTo(path) {
  if(routeHistory !== null) {
    routeHistory.push(path);
  }
}

export default function App(props) {
  return (
    <HashRouter hashType="noslash">
      <Route
        render={({ history }) => {
          routeHistory = history;
          return null;
        }}
      />
      {/* Rest of the App */}
    </HashRouter>
  );
}

1

반응 라우터 -dom : 5.1.2

  • 이 사이트에는 3 개의 페이지가 있으며이 페이지는 모두 브라우저에서 동적으로 렌더링됩니다.

  • 페이지가 새로 고쳐지지는 않지만 사이트를 탐색 할 때 React Router가 URL을 최신 상태로 유지하는 방법에 주목하십시오. 이렇게하면 브라우저 기록이 보존되어 뒤로 버튼 및 책갈피와 같은 기능이 제대로 작동합니다.

  • 스위치는 모든 자식 요소를 통해보고 그 경로는 현재 URL과 일치하는 첫 번째를 렌더링합니다. 경로가 여러 개인 경우 언제든지 사용하지만 한 번에 하나만 렌더링하기를 원합니다.

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";



export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />

        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

// You can think of these components as "pages"
// in your app.

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
    </div>
  );
}```

SO에 오신 것을 환영합니다! 답변이 많은 질문에 답할 때는 자신의 장점을 보여주십시오.
— David García Bodego

이것은 또한 마크 업이 아닌 명령형 js에서 프로그래밍 방식으로 수행하는 방법에 대한 질문에 대답하지 않습니다.
— George Mauer

1

그래서 제 대답에는 프로그래밍 방식으로 경로로 리디렉션하는 3 가지 방법이 있습니다. 일부 솔루션은 이미 제시되었지만 다음 솔루션은 추가 데모 응용 프로그램이있는 기능적 구성 요소 에만 초점을 맞췄습니다 .

다음 버전 사용 :

반응 : 16.13.1

반응-돔 : 16.13.1

반응 라우터 : 5.2.0

반응 라우터 -dom : 5.2.0

타자기 : 3.7.2

구성 :

따라서 먼저 모든 솔루션이 HashRouter다음과 같이 구성되어 있습니다.

<HashRouter>
    // ... buttons for redirect

    <Switch>
      <Route exact path="/(|home)" children={Home} />
      <Route exact path="/usehistory" children={UseHistoryResult} />
      <Route exact path="/withrouter" children={WithRouterResult} />
      <Route exact path="/redirectpush" children={RedirectPushResult} />
      <Route children={Home} />
    </Switch>
</HashRouter>

에 관한 문서에서<HashRouter> :

<Router>URL의 해시 부분 ( window.location.hash)을 사용하여 UI와 URL의 동기화를 유지 하는 A 입니다 .

솔루션 :

  1. 를 사용 <Redirect>하여 푸시 사용 useState:

기능 구성 요소 ( RedirectPushAction내 저장소의 구성 요소)에서 사용 useState하면 리디렉션을 처리 하는 데 사용할 수 있습니다. 까다로운 부분은 리디렉션이 발생하면 redirect상태를 다시로 설정해야 합니다 false. 지연 setTimeOut과 함께 사용 하면 0React가 커밋 될 때까지 기다리고 있습니다.Redirect DOM에 할 다음에 사용할 수 있도록 버튼을 다시 가져옵니다.

아래에서 내 예를 찾으십시오.

const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
    let render = null;
    if (redirect) {
        render = <Redirect to="/redirectpush" push={true} />

        // in order wait until commiting to the DOM
        // and get back the button for clicking next time
        setTimeout(() => setRedirect(false), 0);
    }
    return render;
}, [redirect]);

return <>
    {handleRedirect()}
    <button onClick={() => setRedirect(true)}>
        Redirect push
    </button>
</>

에서 <Redirect>문서 :

를 렌더링하면 <Redirect>새 위치로 이동합니다. 서버 측 리디렉션 (HTTP 3xx)과 같이 새 위치는 기록 스택의 현재 위치보다 우선합니다.

  1. useHistory후크 사용 :

내 솔루션에는 UseHistoryAction다음을 나타내는 구성 요소가 있습니다 .

let history = useHistory();

return <button onClick={() => { history.push('/usehistory') }}>
    useHistory redirect
</button>

useHistory후크는 우리에게 우리에게 프로그램 탐색 또는 변경 경로를하는 데 도움이 역사 개체에 대한 액세스를 제공합니다.

  1. 사용 withRouter의를 얻을 수 history에서 props:

이라는 하나의 구성 요소를 작성 WithRouterAction하면 다음과 같이 표시됩니다.

const WithRouterAction = (props:any) => {
    const { history } = props;

    return <button onClick={() => { history.push('/withrouter') }}>
        withRouter redirect
    </button>
}

export default withRouter(WithRouterAction);

withRouter문서 에서 읽기 :

고차 컴포넌트 를 통해 history객체의 속성 및 가장 가까운 <Route>일치 항목에 액세스 할 수 있습니다 withRouter. withRouter업데이트 될 때마다 업데이트 된 match, location및 history소품을 래핑 된 구성 요소에 전달 합니다.

데모:

더 나은 표현을 위해 이러한 예제를 사용하여 GitHub 리포지토리를 만들었습니다. 아래에서 찾으십시오.

https://github.com/norbitrial/react-router-programmatically-redirect-examples

이게 도움이 되길 바란다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.