Làm thế nào để lấy lịch sử trên react-router v4?


101

Tôi gặp một số vấn đề nhỏ khi di chuyển từ React-Router v3 sang v4. trong v3, tôi có thể thực hiện việc này ở bất cứ đâu:

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

Làm cách nào để đạt được điều này trong v4.

Tôi biết rằng tôi có thể sử dụng các withRouterđạo cụ bộ định tuyến sự kiện, ngữ cảnh hoc , hoặc sự kiện khi bạn ở trong một Thành phần. nhưng nó không phải là trường hợp của tôi.

Tôi đang tìm kiếm sự tương đương của NavigationOutsideOfComponents trong v4


1
Cảm ơn @Chris, nhưng như tôi đã nói, tôi không ở trong Thành phần.
bão_buster

@ Chris trong một lớp tiện ích, xin vui lòng kiểm tra github.com/ReactTraining/react-router/blob/master/docs/guides/... , nó có thể là một middlewarere Redux hoặc bất cứ điều gì khác
storm_buster


Tôi đã kết thúc bằng cách sử dụng BrowserRouter làm thành phần gốc. Bằng cách đó, tôi có thể sử dụng thành phần Ứng dụng vớiRouter. Không chính xác những gì bạn yêu cầu nhưng tôi có những yêu cầu tương tự và điều này là đủ đối với tôi.
The Fool

Câu trả lời:


180

Bạn chỉ cần có một mô-đun xuất một historyđối tượng. Sau đó, bạn sẽ nhập đối tượng đó trong suốt dự án của mình.

// history.js
import { createBrowserHistory } from 'history'

export default createBrowserHistory({
  /* pass a configuration object here if needed */
})

Sau đó, thay vì sử dụng một trong các bộ định tuyến tích hợp, bạn sẽ sử dụng <Router>thành phần này.

// index.js
import { Router } from 'react-router-dom'
import history from './history'
import App from './App'

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder)
// some-other-file.js
import history from './history'
history.push('/go-here')

1
Cảm ơn rất nhiều! Hiện tại, bằng cách sử dụng react-router4, tôi phải sử dụng lần nhập này trong history.js để thay thế: import createBrowserHistory từ 'history / createBrowserHistory';
peter.bartos

3
Nó có hiệu quả với tôi khi tôi đặt history = {history} trong Route và vượt qua như một đạo cụ
Nath Paiva

1
chúng ta có thể sử dụng withHistory và lấy lịch sử trong các đạo cụ thay vì tạo tệp riêng biệt. giải pháp này không hoạt động với tôi với redux.
Zeel Shah

4
Nhập createHashHistorynếu bạn đang sử dụng HashRouter.
David Harkness

2
@HassanAzzam Có thể bạn đang sử dụng react-router V5 và câu trả lời này phù hợp với V4, không phải V5. Tôi hiện đang gặp phải thách thức tương tự và đang tìm kiếm khắp mọi nơi, nhưng không thể thực hiện được. history.push bên ngoài thành phần hoạt động, nhưng nhấp vào Liên kết thì không nữa.
Waterlink

71

Những công việc này! https://reacttraining.com/react-router/web/api/withRouter

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

class MyComponent extends React.Component {
  render () {
    this.props.history;
  }
}

withRouter(MyComponent);

26
miễn là bạn đang ở trong một thành phần. Tôi không phải là trong một thành phần
storm_buster

1
Cảm ơn bạn, đây là cách dễ dàng và đơn giản nhất để liên kết đến một tuyến đường khác từ một thành phần. Tôi chỉ nói thêm rằng bạn cần phải làm gì this.props.history.push('/some_route');để nó hoạt động.
dannytenaglias

1
@storm_buster const Component = props => {... // stuff}export default withRouter(Component)công trình đối với tôi trên một thành phần không quốc tịch
Karl Taylor

10

Mô phỏng để trả lời được chấp nhận những gì bạn có thể làm là sử dụng reactreact-routerchính nó để cung cấp cho bạnhistory đối tượng mà bạn có thể phân bổ trong một tệp và sau đó xuất.

history.js

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

// variable which will point to react-router history
let globalHistory = null;

// component which we will mount on top of the app
class Spy extends React.Component {
  constructor(props) {
    super(props)
    globalHistory = props.history; 
  }

  componentDidUpdate() {
    globalHistory = this.props.history;
  }

  render(){
    return null;
  }
}

export const GlobalHistory = withRouter(Spy);

// export react-router history
export default function getHistory() {    
  return globalHistory;
}

Sau đó, bạn nhập Thành phần và gắn kết để khởi tạo biến lịch sử:

import { BrowserRouter } from 'react-router-dom';
import { GlobalHistory } from './history';

function render() {
  ReactDOM.render(
    <BrowserRouter>
        <div>
            <GlobalHistory />
            //.....
        </div>
    </BrowserRouter>
    document.getElementById('app'),
  );
}

Và sau đó, bạn chỉ có thể nhập vào ứng dụng của mình khi nó đã được gắn kết:

import getHistory from './history'; 

export const goToPage = () => (dispatch) => {
  dispatch({ type: GO_TO_SUCCESS_PAGE });
  getHistory().push('/success'); // at this point component probably has been mounted and we can safely get `history`
};

Tôi thậm chí đã thực hiện và gói npm làm được điều đó.


Kể từ reactjs 16.9, giải pháp này sẽ đưa ra cảnh báo không dùng nữa trên componentWillMount và componentWillReceiveProps.
ian

1
@ian đúng, cố định
Tomasz Mularczyk

5

Nếu bạn đang sử dụng redux và redux-thunk, giải pháp tốt nhất sẽ là sử dụng react-router-redux

// then, in redux actions for example
import { push } from 'react-router-redux'

dispatch(push('/some/path'))

Điều quan trọng là phải xem tài liệu để thực hiện một số cấu hình.


1
Tôi đến đây với hy vọng tìm ra giải pháp chính xác này, cảm ơn bạn
vapurrmaid

4

Dựa trên câu trả lời này nếu bạn chỉ cần đối tượng lịch sử để điều hướng đến thành phần khác:

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

SAI, bạn đang ở trong một thành phần. xem // some-other-file.js từ câu trả lời được chấp nhận
Storm_buster

0

Trong App.js

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

 const TheContext = React.createContext(null);

 const App = () => {
   const history = useHistory();

   <TheContext.Provider value={{ history, user }}>

    <Switch>
        <Route exact path="/" render={(props) => <Home {...props} />} />
        <Route
          exact
          path="/sign-up"
          render={(props) => <SignUp {...props} setUser={setUser} />}
        /> ...

Sau đó, trong một thành phần con:

const Welcome = () => {
    
    const {user, history} = React.useContext(TheContext); 
    ....

-2

Trong trường hợp cụ thể của react-router, việc sử dụng contextlà một trường hợp hợp lệ, ví dụ:

class MyComponent extends React.Component {
  props: PropsType;

  static contextTypes = {
    router: PropTypes.object
  };

  render () {
    this.context.router;
  }
}

Bạn có thể truy cập một phiên bản của lịch sử thông qua bối cảnh bộ định tuyến, ví dụ this.context.router.history.


Câu hỏi cụ thể là hỏi về thời điểm bên ngoài một thành phần nên this.context không khả dụng như một tùy chọn:> "Tôi biết rằng tôi có thể sử dụng, các đạo cụ học vớiRouter, phản ứng hoặc bộ định tuyến sự kiện khi bạn ở trong Thành phần. Nhưng nó không phải là trường hợp của tôi. "
SunshinyDoyle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.