Điều hướng theo chương trình bằng bộ định tuyến phản ứng

1626
George Mauer 2015-06-27 07:38.

Với react-routertôi có thể sử dụng Linkphần tử để tạo liên kết được xử lý nguyên bản bởi bộ định tuyến phản ứng.

Tôi thấy nội bộ nó kêu gọi this.context.transitionTo(...).

Tôi muốn điều hướng. Không phải từ một liên kết mà từ một lựa chọn thả xuống (làm ví dụ). Làm thế nào tôi có thể làm điều này trong mã? Là this.contextgì?

Tôi đã thấy Navigationhỗn hợp, nhưng tôi có thể làm điều này mà không có mixins?

30 answers

1708
Paul S 2017-02-09 08:39.

React Router v5.1.0 với hooks

Có một useHistoryhook mới trong React Router> 5.1.0 nếu bạn đang sử dụng React> 16.8.0 và các thành phần chức năng.

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

Bộ định tuyến React v4

Với phiên bản 4 của React Router, có ba cách tiếp cận mà bạn có thể thực hiện để định tuyến theo chương trình trong các thành phần.

  1. Sử dụng thành phần withRouterbậc cao hơn.
  2. Sử dụng bố cục và kết xuất <Route>
  3. Sử dụng context.

React Router chủ yếu là một trình bao bọc xung quanh historythư viện. historyxử lý tương tác với trình duyệt window.historycho bạn bằng trình duyệt và lịch sử băm của nó. Nó cũng cung cấp lịch sử bộ nhớ hữu ích cho các môi trường không có lịch sử toàn cầu. Điều này đặc biệt hữu ích trong phát triển ứng dụng dành cho thiết bị di động ( react-native) và thử nghiệm đơn vị với Node.

Một historyphiên bản có hai phương pháp để điều hướng: pushreplace. Nếu bạn historycoi nó là một mảng các vị trí đã truy cập, pushsẽ thêm một vị trí mới vào mảng và replacesẽ thay thế vị trí hiện tại trong mảng bằng vị trí mới. Thông thường, bạn sẽ muốn sử dụng pushphương pháp này khi bạn đang điều hướng.

Trong các phiên bản trước đó của Phản ứng Router, bạn phải tạo riêng của bạn historychẳng hạn, nhưng trong v4 sự <BrowserRouter>, <HashRouter><MemoryRouter>các thành phần sẽ tạo ra một trình duyệt, băm, và trường hợp bộ nhớ cho bạn. React Router làm cho các thuộc tính và phương thức của historycá thể được liên kết với bộ định tuyến của bạn có sẵn thông qua ngữ cảnh, bên dưới routerđối tượng.

1. Sử dụng thành phần withRouterbậc cao hơn

Thành phần withRouterbậc cao hơn sẽ đưa historyđối tượng vào làm chỗ dựa của thành phần. Điều này cho phép bạn truy cập pushreplacecác phương thức mà không cần phải xử lý 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. Sử dụng bố cục và kết xuất <Route>

Thành <Route>phần này không chỉ dành cho các vị trí phù hợp. Bạn có thể hiển thị một tuyến đường không có đường dẫn và nó sẽ luôn khớp với vị trí hiện tại . Thành <Route>phần chuyển các đạo cụ giống như withRouter, vì vậy bạn sẽ có thể truy cập các historyphương thức thông qua phần historyhỗ trợ.

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

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

3. Sử dụng ngữ cảnh *

Nhưng có lẽ bạn không nên

Tùy chọn cuối cùng là tùy chọn mà bạn chỉ nên sử dụng nếu bạn cảm thấy thoải mái khi làm việc với mô hình ngữ cảnh của React (API ngữ cảnh của React là ổn định kể từ 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 và 2 là những lựa chọn đơn giản nhất để thực hiện, vì vậy đối với hầu hết các trường hợp sử dụng, chúng là những lựa chọn tốt nhất của bạn.

964
Felipe Skinner 2015-06-27 07:49.

Câu trả lời React-Router 5.1.0+ (sử dụng hook và React> 16.8)

Bạn có thể sử dụng useHistoryhook mới trên Các thành phần chức năng và điều hướng theo chương trình:

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

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

Câu trả lời React-Router 4.0.0+

Trong phiên bản 4.0 trở lên, hãy sử dụng lịch sử làm chỗ dựa cho thành phần của bạn.

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

LƯU Ý: this.props.history không tồn tại trong trường hợp thành phần của bạn không được hiển thị bởi <Route>. Bạn nên sử dụng <Route path="..." component={YourComponent}/>this.props.history trong YourComponent

Câu trả lời React-Router 3.0.0+

Trong phiên bản 3.0 trở lên, hãy sử dụng bộ định tuyến làm chỗ dựa cho thành phần của bạn.

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

Câu trả lời React-Router 2.4.0+

Trong phiên bản 2.4 trở lên, hãy sử dụng thành phần thứ tự cao hơn để lấy bộ định tuyến làm chỗ dựa cho thành phần của bạn.

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

Câu trả lời React-Router 2.0.0+

Phiên bản này tương thích ngược với 1.x nên không cần phải có Hướng dẫn nâng cấp. Chỉ cần xem qua các ví dụ là đủ tốt.

Điều đó nói rằng, nếu bạn muốn chuyển sang mẫu mới, có một mô-đun browserHistory bên trong bộ định tuyến mà bạn có thể truy cập bằng

import { browserHistory } from 'react-router'

Bây giờ bạn có quyền truy cập vào lịch sử trình duyệt của mình, vì vậy bạn có thể thực hiện những việc như đẩy, thay thế, v.v ... Như:

browserHistory.push('/some/path')

Đọc thêm: Lịch sửĐiều hướng


Câu trả lời React-Router 1.xx

Tôi sẽ không đi vào chi tiết nâng cấp. Bạn có thể đọc về điều đó trong Hướng dẫn nâng cấp

Thay đổi chính về câu hỏi ở đây là thay đổi từ Điều hướng mixin thành Lịch sử. Bây giờ nó đang sử dụng lịch sử trình duyệtAPI để thay đổi lộ trình, vì vậy chúng tôi sẽ sử dụng pushState()từ bây giờ.

Đây là một ví dụ sử dụng Mixin:

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

Lưu ý rằng điều này Historyđến từ dự án rackt / history . Không phải từ chính React-Router.

Nếu bạn không muốn sử dụng Mixin vì một lý do nào đó (có thể vì lớp ES6), thì bạn có thể truy cập lịch sử mà bạn nhận được từ bộ định tuyến this.props.history. Nó sẽ chỉ có thể truy cập được đối với các thành phần do Bộ định tuyến của bạn hiển thị. Vì vậy, nếu bạn muốn sử dụng nó trong bất kỳ thành phần con nào, nó cần phải được truyền dưới dạng một thuộc tính qua props.

Bạn có thể đọc thêm về bản phát hành mới tại tài liệu 1.0.x của họ

Đây là trang trợ giúp cụ thể về cách điều hướng bên ngoài thành phần của bạn

Nó khuyên bạn nên lấy một tài liệu tham khảo history = createHistory()và kêu gọi replaceStateđiều đó.

Câu trả lời React-Router 0.13.x

Tôi gặp phải vấn đề tương tự và chỉ có thể tìm ra giải pháp với bộ trộn Điều hướng đi kèm với bộ định tuyến phản ứng.

Đây là cách tôi đã làm điều đó

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

Tôi đã có thể gọi điện transitionTo()mà không cần truy cập.context

Hoặc bạn có thể thử ES6 ưa thích 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
};

React-Router-Redux

Lưu ý: nếu bạn đang sử dụng Redux, có một dự án khác có tên là React-Router-Redux cung cấp cho bạn các liên kết redux cho ReactRouter, sử dụng tương tự như cách tiếp cận mà React-Redux thực hiện

React-Router-Redux có sẵn một số phương pháp cho phép điều hướng đơn giản từ các trình tạo hành động bên trong. Những điều này có thể đặc biệt hữu ích cho những người có kiến ​​trúc hiện có trong React Native và họ muốn sử dụng các mẫu tương tự trong React Web với chi phí tối thiểu cho bảng soạn sẵn.

Khám phá các phương pháp sau:

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

Đây là một ví dụ sử dụng với 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>
515
Bobby 2016-01-19 10:32.

React-Router v2

Đối với bản phát hành gần đây nhất ( v2.0.0-rc5), phương pháp điều hướng được khuyến nghị là đẩy trực tiếp vào singleton lịch sử. Bạn có thể thấy điều đó đang hoạt động trong tài liệu Điều hướng bên ngoài Thành phần .

Đoạn trích liên quan:

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

Nếu sử dụng API bộ định tuyến phản ứng mới hơn, bạn cần tận dụng tính năng historytừ this.propskhi bên trong của các thành phần để:

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

Nó cũng cung cấp pushStatenhưng điều đó không được chấp nhận cho mỗi cảnh báo đã ghi.

Nếu sử dụng react-router-redux, nó cung cấp một pushchức năng mà bạn có thể gửi như sau:

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

Tuy nhiên, điều này có thể chỉ được sử dụng để thay đổi URL, không thực sự điều hướng đến trang.

58
Alex Miller 2016-01-23 10:46.

Đây là cách bạn làm điều này react-router v2.0.0với ES6 . react-routerđã rời khỏi mixin.

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
}
57
Eric Martin 2017-06-07 12:14.

React-Router 4.x Trả lời:

Về phần mình, tôi muốn có một đối tượng lịch sử duy nhất mà tôi có thể mang theo cả các thành phần bên ngoài. Những gì tôi muốn làm là có một tệp history.js duy nhất mà tôi nhập theo yêu cầu và chỉ cần thao tác với nó.

Bạn chỉ cần thay đổi BrowserRouterthành Bộ định tuyến và chỉ định hỗ trợ lịch sử. Điều này không thay đổi bất kỳ điều gì đối với bạn ngoại trừ việc bạn có đối tượng lịch sử của riêng mình mà bạn có thể thao tác theo ý muốn.

Bạn cần cài đặt lịch sử , thư viện được sử dụng bởi react-router.

Cách sử dụng ví dụ, ký hiệu 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>;
    }
}

CHỈNH SỬA ngày 16 tháng 4 năm 2018:

Nếu bạn phải điều hướng từ một thành phần thực sự được hiển thị từ một Routethành phần, bạn cũng có thể truy cập lịch sử từ các đạo cụ, như sau:

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>;
    }
}
48
Alexey Volodko 2016-03-20 02:59.

Đối với điều này, ai không kiểm soát phía máy chủ và vì điều này đang sử dụng bộ định tuyến băm v2:

Đặt lịch sử của bạn vào tệp riêng biệt (ví dụ: app_history.js ES6):

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

export default appHistory;

Và sử dụng nó ở mọi nơi!

Điểm vào của bạn cho bộ định tuyến phản ứng (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"]'));

Điều hướng của bạn bên trong bất kỳ thành phần nào (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()
  }
})
44
Lyubomir 2017-11-23 00:59.

CHỈNH SỬA: React Router v6

Tôi đã không chạm vào React trong một thời gian, nhưng muốn cảm ơn và đánh dấu nhận xét bên dưới của @Shimrit Snapir

on React-Router 6.0 <Redirect /> changed to <Navigate />

Bộ định tuyến React V4

tl: dr;

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

Câu trả lời đơn giản và mang tính khai báo là bạn cần sử dụng <Redirect to={URL} push={boolean} />kết hợp vớisetState()

push: boolean - khi true, chuyển hướng sẽ đẩy một mục mới vào lịch sử thay vì thay thế mục hiện tại.


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

Ví dụ đầy đủ ở đây . Đọc thêm tại đây .

Tái bút. Ví dụ sử dụng ES7 + Bộ khởi tạo thuộc tính để khởi tạo trạng thái. Nhìn vào đây , nếu bạn quan tâm.

32
Qiming 2015-06-30 20:14.

Cảnh báo: câu trả lời này chỉ bao gồm các phiên bản ReactRouter trước 1.0

Tôi sẽ cập nhật câu trả lời này với các trường hợp sử dụng 1.0.0-rc1 sau!

Bạn có thể làm điều này mà không cần mixin.

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

Gotcha với các ngữ cảnh là nó không thể truy cập được trừ khi bạn xác định contextTypestrên lớp.

Đối với bối cảnh là gì, nó là một đối tượng, giống như đạo cụ, được truyền từ cha mẹ sang con, nhưng nó được truyền lại một cách ngầm định, không cần phải khai báo lại các đạo cụ mỗi lần. Xem https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html

28
Ben Wheeler 2016-12-01 04:02.

Tôi đã thử ít nhất 10 cách để làm điều này trước khi cách nào đó hoạt động đúng!

withRouterCâu trả lời của @Felipe Skinner khiến tôi hơi choáng ngợp và tôi không chắc mình muốn tạo tên lớp "ExportedWithRouter" mới.

Đây là cách đơn giản và rõ ràng nhất để làm điều đó, áp dụng cho React-Router 3.0.0 và ES6 hiện tại:

React-Router 3.xx với ES6:

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

hoặc, nếu đó không phải là lớp mặc định của bạn, hãy xuất như:

withRouter(Example);
export { Example };

Lưu ý rằng trong 3.xx, <Link>chính thành phần đang sử dụng router.push, vì vậy bạn có thể chuyển nó bất cứ thứ gì bạn muốn chuyển <Link to=thẻ, như:

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
23
Alireza 2017-05-15 22:53.

Để thực hiện điều hướng theo chương trình, bạn cần phải đẩy một lịch sử mới vào props.history trong của bạn component, vì vậy những thứ như thế này có thể thực hiện công việc cho bạn:

//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;
20
mcku 2016-09-28 11:32.

Có thể không phải là cách tiếp cận tốt nhất nhưng ... Sử dụng react-router v4, các Typecript sau đây có thể đưa ra một số ý tưởng.

Trong thành phần được hiển thị bên dưới, ví dụ LoginPage, routerđối tượng có thể truy cập được và chỉ cần gọi router.transitionTo('/homepage')để điều hướng.

Mã điều hướng đã được lấy từ .

"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')
);

19
Softwareddy 2016-09-13 12:00.

Đối với các thành phần ES6 + React, giải pháp sau đây phù hợp với tôi.

Tôi đã theo dõi Felippe skinner, nhưng đã thêm giải pháp kết thúc để giúp những người mới bắt đầu như tôi.

Dưới đây là các phiên bản tôi đã sử dụng:

"react-router": "^ 2.7.0"

"react": "^ 15.3.1"

Dưới đây là thành phần phản ứng của tôi, nơi tôi đã sử dụng điều hướng có lập trình bằng bộ định tuyến phản ứng:

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;

Dưới đây là cấu hình cho bộ định tuyến của tôi:

 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'));
18
Hossein 2017-09-17 19:54.

Trong React-Router v4ES6

Bạn có thể sử dụng withRouterthis.props.history.push.

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

class Home extends Component {

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

export default withRouter(Home);
15
Janos 2018-05-28 23:02.

Để sử dụng withRoutervới một thành phần dựa trên lớp, hãy thử một cái gì đó như thế này bên dưới. Đừng quên thay đổi câu lệnh xuất để sử dụng 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);
13
peter.mouland 2016-09-15 22:00.

với React-Router v4 trên đường chân trời, hiện có một cách mới để thực hiện việc này.

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 là một ứng dụng ví dụ hiển thị cách sử dụng / cập nhật react-router và nó bao gồm các bài kiểm tra chức năng mẫu để điều hướng ứng dụng.

12
Dan 2016-12-23 22:15.

dựa trên câu trả lời trước
của José Antonio Postigo và Ben Wheeler
, tính mới? sẽ được viết bằng Typecript
và việc sử dụng trình trang trí
HOẶC thuộc tính tĩnh / trường

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

với bất kỳ npm nào được cài đặt ngày hôm nay. "react-router": "^ 3.0.0" và
"@ type / react-router": "^ 2.0.41"

12
saiful619945 2018-08-14 20:33.

Trong bộ định tuyến phản ứng v4. Tôi làm theo hai cách này để định tuyến theo chương trình.

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

Số hai

Thay thế mục nhập hiện tại trên ngăn xếp lịch sử

Để có được lịch sử trong các đạo cụ, bạn có thể phải bọc thành phần của mình bằng

withRouter

10
Zaman Afzal 2017-08-19 00:50.

Nếu bạn đang sử dụng băm hoặc lịch sử trình duyệt thì bạn có thể làm

hashHistory.push('/login');
browserHistory.push('/login');
8
José Antonio Postigo 2016-09-30 02:04.

Với phiên bản React hiện tại (15.3), this.props.history.push('/location');đã hoạt động với tôi, nhưng nó cho thấy cảnh báo sau:

browser.js: 49 Cảnh báo: [react-router] props.historycontext.historykhông được dùng nữa. Hãy sử dụng context.router.

và tôi đã giải quyết nó bằng cách sử dụng context.routernhư thế này:

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;
7
Garry Taylor 2016-11-04 07:43.

React-Router V4

nếu bạn đang sử dụng phiên bản 4 thì bạn có thể sử dụng thư viện của tôi (plugin Shameless), nơi bạn chỉ cần gửi một hành động và mọi thứ chỉ hoạt động!

dispatch(navigateTo("/aboutUs"));

trippler

6
reflexgravity 2018-11-30 21:40.

Những người đang gặp phải vấn đề trong việc triển khai điều này trên react-router v4.

Đây là một giải pháp hiệu quả để điều hướng trong ứng dụng react từ các hành động 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 HOẶC tệp redux

import history from './history' 

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

Tất cả là nhờ vào nhận xét này: Nhận xét về các vấn đề ReactTraining

6
Nickofthyme 2019-10-06 09:23.

Bạn cũng có thể sử dụng useHistoryhook trong một thành phần không trạng thái. Ví dụ từ tài liệu.

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

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

Lưu ý: Các móc đã được thêm vào [email protected]và yêu cầu[email protected]>=16.8

4
webmaster 2018-02-02 15:25.

Câu trả lời đúng cho tôi tại thời điểm viết bài

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

Nhưng bạn cần thêm PropTypes vào thành phần của mình

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

Đừng quên nhập PropTypes

import PropTypes from 'prop-types';
4
neatsu 2017-12-08 07:26.

Có thể không phải là giải pháp tốt nhất nhưng nó sẽ hoàn thành công việc:

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

Về cơ bản, một logic gắn liền với một hành động (trong trường hợp này là xóa bài đăng) sẽ kết thúc việc gọi kích hoạt chuyển hướng. Điều này không lý tưởng vì bạn sẽ thêm 'trình kích hoạt' nút DOM vào đánh dấu của mình để bạn có thể gọi nó một cách thuận tiện khi cần. Ngoài ra, bạn sẽ trực tiếp tương tác với DOM, điều này có thể không được mong muốn trong một thành phần React.

Tuy nhiên, loại chuyển hướng này không được yêu cầu thường xuyên. Vì vậy, một hoặc hai liên kết phụ, ẩn trong đánh dấu thành phần của bạn sẽ không ảnh hưởng nhiều đến vậy, đặc biệt nếu bạn đặt cho chúng những cái tên có ý nghĩa.

4
Xlee 2018-05-07 20:43.

Nếu tình cờ ghép nối RR4 w / redux thông qua react -router-redux , sử dụng các trình tạo hành động định tuyến react-router-reduxcũng là một lựa chọn.

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)

Nếu sử dụng redux thunk / saga để quản lý luồng không đồng bộ, hãy nhập các trình tạo hành động ở trên trong các hành động của redux và hook để phản ứng các thành phần bằng mapDispatchToProps có thể tốt hơn.

4
Vijay122 2020-06-19 04:56.

Cập nhật: React Router v6 with hooks

import {useNavigate} from 'react-router-dom';
let navigate = useNavigate();
navigate('home');

Và để di chuyển qua lịch sử trình duyệt,

navigate(-1); ---> Go back
navigate(1);  ---> Go forward
navigate(-2); ---> Move two steps backward.
3
JJ_Coder4Hire 2019-08-23 21:34.

Điều này làm việc cho tôi, không cần nhập khẩu đặc biệt:

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>
3
norbitrial 2019-11-25 05:04.

Vì vậy, trong câu trả lời của tôi, có 3 cách khác nhau để chuyển hướng theo chương trình đến một tuyến đường. Một số giải pháp đã được trình bày nhưng những giải pháp sau đây chỉ tập trung cho các thành phần chức năng với một ứng dụng demo bổ sung.

Sử dụng các phiên bản sau:

phản ứng: 16.13.1

react -dom: 16.13.1

react-router: 5.2.0

react-router-dom: 5.2.0

ký tự: 3.7.2

Cấu hình:

Vì vậy, trước hết giải pháp đang sử dụng HashRouter, được cấu hình như sau:

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

Từ tài liệu về <HashRouter>:

A <Router>sử dụng phần băm của URL (tức là window.location.hash) để giữ cho giao diện người dùng của bạn đồng bộ với URL.

Các giải pháp:

  1. Sử dụng <Redirect>để đẩy bằng cách sử dụng useState:

Sử dụng trong một thành phần chức năng ( RedirectPushActionthành phần từ kho lưu trữ của tôi), chúng ta có thể sử dụng useStateđể xử lý chuyển hướng. Một phần khó khăn là một khi chuyển hướng xảy ra, chúng ta cần thiết lập redirectlại trạng thái false. Bằng cách sử dụng setTimeOutvới 0độ trễ, chúng tôi sẽ đợi cho đến khi React cam kết Redirectvới DOM rồi lấy lại nút để sử dụng lần sau.

Vui lòng tìm ví dụ của tôi bên dưới:

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

Từ <Redirect>tài liệu:

Hiển thị một <Redirect>sẽ điều hướng đến một vị trí mới. Vị trí mới sẽ ghi đè vị trí hiện tại trong ngăn xếp lịch sử, giống như chuyển hướng phía máy chủ (HTTP 3xx).

  1. Sử dụng useHistorymóc:

Trong giải pháp của tôi, có một thành phần được gọi là UseHistoryActionđại diện cho những điều sau:

let history = useHistory();

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

Cái useHistorymóc cung cấp cho chúng tôi quyền truy cập vào đối tượng lịch sử giúp chúng tôi điều hướng hoặc thay đổi các tuyến đường theo chương trình.

  1. Sử dụng withRouter, lấy historytừ props:

Đã tạo một thành phần được gọi WithRouterAction, hiển thị như sau:

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

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

export default withRouter(WithRouterAction);

Đọc từ withRoutertài liệu:

Bạn có thể truy cập vào các historythuộc tính của đối tượng và đối tượng gần nhất <Route>thông qua thành phần withRouterbậc cao hơn. withRoutersẽ vượt qua được cập nhật match, locationhistoryđạo cụ để các thành phần quấn bất cứ khi nào nó ám.

Bản giới thiệu:

Để trình bày tốt hơn, tôi đã xây dựng một kho lưu trữ GitHub với các ví dụ này, vui lòng tìm nó bên dưới:

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

Tôi hi vọng cái này giúp được!

3
StefanBob 2020-01-16 08:44.

Hãy thử hookrouter, "giải pháp thay thế hiện đại cho bộ định tuyến phản ứng"

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

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

để trả lời câu hỏi OP về liên kết thông qua hộp chọn, bạn có thể thực hiện:

navigate('/about');

*** CẬP NHẬT CÂU TRẢ LỜI ***

Tôi nghĩ hook-router là một bộ khởi động tốt và giúp tôi tìm hiểu về định tuyến nhưng kể từ đó đã được cập nhật lên react-router để xử lý lịch sử và tham số truy vấn của nó.

import { useLocation, useHistory } from 'react-router-dom';


const Component = (props) => {
    const history = useHistory();
    
    // Programmatically navigate
    history.push(newUrlString);
}

Bạn đẩy nơi bạn muốn điều hướng vào location.history.

2
Aftab Khan 2019-05-23 22:57.

Đối với React Router v4 +

Giả sử rằng bạn sẽ không cần điều hướng trong quá trình hiển thị ban đầu (mà bạn có thể sử dụng <Redirect>component), đây là những gì chúng tôi đang làm trong ứng dụng của mình.

Xác định một tuyến rỗng trả về null, điều này sẽ cho phép bạn có quyền truy cập vào đối tượng lịch sử. Bạn cần thực hiện việc này ở cấp cao nhất mà bạn Routerđược xác định.

Bây giờ bạn có thể làm tất cả những gì có thể được thực hiện trên lịch sử như history.push(), history.replace(), history.go(-1)vv!

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

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Sau khi Sarah Palin tán thành Donald Trump vào đầu tuần này, gần như không thể tránh khỏi việc Tina Fey sẽ trở lại Saturday Night Live để thăm lại ấn tượng Palin cổ điển của cô. Và Fey chắc chắn đã không làm thất vọng, cô ấy đã đưa ra một lời khen ngợi không hề nhẹ về bài phát biểu chứng thực Iowa quanh co và khó hiểu của Palin trong khi Trump của Darrell Hammond đưa ra bình luận xuyên suốt.

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Chúng ta có thể thấy nhiều hơn nữa về một Julio Jones khỏe mạnh trong khu vực cuối năm nay. John Parker Wilson, Greg McElroy, A.

Đó phải là Đức

Đó phải là Đức

Đối với đội tuyển Anh, không có kẻ thủ ác nào lớn hơn Hầu hết các cổ động viên Anh, nếu không muốn nói là tất cả, hẳn sẽ phải gật gù khi tiếng còi mãn cuộc của trận bán kết lượt về W Euro 2022 vang lên. Bởi vì nó báo hiệu rằng Đức sẽ chờ đợi ở Wembley trong trận chung kết với Anh và là điều duy nhất giữa Anh và chiếc cúp lớn đầu tiên của đội tuyển nữ.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language