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


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

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

1. withRouter고차 부품 사용

withRouter고차 성분을 분사 할 history컴포넌트의 소품으로 개체. 이를 통해 를 처리하지 않고도 pushreplace메소드 에 액세스 할 수 있습니다 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

에서 반작용-라우터 V4ES6

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.historycontext.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, locationhistory소품을 래핑 된 구성 요소에 전달 합니다.

데모:

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

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

이게 도움이 되길 바란다!

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