React-router: Làm thế nào để gọi Link bằng tay?


131

Tôi mới biết về ReactJS và React-Router. Tôi có một thành phần nhận thông qua đạo cụ một <Link/>đối tượng từ bộ định tuyến phản ứng . Bất cứ khi nào người dùng nhấp vào nút 'tiếp theo' bên trong thành phần này, tôi muốn gọi <Link/>đối tượng theo cách thủ công.

Ngay bây giờ, tôi đang sử dụng ref để truy cập vào thể hiện sao lưu và nhấp thủ công vào thẻ 'a' <Link/>tạo ra.

Câu hỏi: Có cách nào để gọi Liên kết thủ công (ví dụ this.props.next.go) không?

Đây là mã hiện tại tôi có:

//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />

//in Document.js
...
var Document = React.createClass({
   _onClickNext: function() {
      var next = this.refs.next.getDOMNode();
      next.querySelectorAll('a').item(0).click(); //this sounds like hack to me
   },
   render: function() {
      return (
         ...
         <div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>
         ...
      );
   }
});
...

Đây là mã tôi muốn có:

//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />

//in Document.js
...
var Document = React.createClass({
   render: function() {
      return (
         ...
         <div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png" /> </div>
         ...
      );
   }
});
...

Câu trả lời:


198

React Router v4 - Thành phần chuyển hướng (cập nhật 2017/04/15)

Cách v4 được đề xuất là cho phép phương thức kết xuất của bạn bắt được chuyển hướng. Sử dụng trạng thái hoặc đạo cụ để xác định xem thành phần chuyển hướng có cần được hiển thị không (sau đó kích hoạt chuyển hướng).

import { Redirect } from 'react-router';

// ... your class implementation

handleOnClick = () => {
  // some action...
  // then redirect
  this.setState({redirect: true});
}

render() {
  if (this.state.redirect) {
    return <Redirect push to="/sample" />;
  }

  return <button onClick={this.handleOnClick} type="button">Button</button>;
}

Tham khảo: https://reacttraining.com/react-router/web/api/Redirect

React Router v4 - Bối cảnh bộ định tuyến tham chiếu

Bạn cũng có thể tận dụng Routerbối cảnh tiếp xúc với thành phần React.

static contextTypes = {
  router: PropTypes.shape({
    history: PropTypes.shape({
      push: PropTypes.func.isRequired,
      replace: PropTypes.func.isRequired
    }).isRequired,
    staticContext: PropTypes.object
  }).isRequired
};

handleOnClick = () => {
  this.context.router.push('/sample');
}

Đây là cách làm <Redirect />việc dưới mui xe.

Tham khảo: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60

React Router v4 - Đối tượng lịch sử đột biến bên ngoài

Nếu bạn vẫn cần phải làm một cái gì đó tương tự như triển khai của v2, bạn có thể tạo một bản sao BrowserRoutersau đó hiển thị historydưới dạng hằng số có thể xuất. Dưới đây là một ví dụ cơ bản nhưng bạn có thể soạn nó để tiêm nó với các đạo cụ tùy biến nếu cần. Có những lưu ý cần chú ý với vòng đời, nhưng nó phải luôn luôn chạy lại Router, giống như trong v2. Điều này có thể hữu ích cho các chuyển hướng sau khi yêu cầu API từ một chức năng hành động.

// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';

export const history = createHistory();

export default class BrowserRouter extends Component {
  render() {
    return <Router history={history} children={this.props.children} />
  }
}

// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';

render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>
);

// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';

history.push('/sample');

Mới nhất BrowserRouterđể gia hạn: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js

Bộ định tuyến phản ứng v2

Đẩy một trạng thái mới vào browserHistorythể hiện:

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

Tham khảo: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md


7
hashHistory.push ('/ mẫu'); nếu bạn đang sử dụng hashHistory thay vì browserHistory
sanath_p

1
điều này đặc biệt hữu ích trong thư viện tài liệu-ui vì sử dụng containerEuity = {<Link to = "/" />} không phải lúc nào cũng gọi liên kết
Vishal Disawar

2
Lưu ý với tùy chọn chuyển hướng, bạn phải chỉ định đẩy (tức là <Chuyển hướng đẩy />). Theo mặc định, nó sẽ thực hiện một thay thế hoàn toàn không giống như gọi thủ công một Liên kết
aw04

1
@jokab bạn có thể sử dụng <NavLink /> thay vì <Link /> github.com/ReactTraining/react-router/blob/master/packages/ Lỗi
Matt Lo

1
Redirect không hoạt động với tôi, nhưng giải pháp aw04 với withRouter đơn giản và hiệu quả hơn
stackdave

90

React Router 4 bao gồm withRouter HOC cho phép bạn truy cập vào historyđối tượng thông qua this.props:

import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'

class Foo extends Component {
  constructor(props) {
    super(props)

    this.goHome = this.goHome.bind(this)
  }

  goHome() {
    this.props.history.push('/')
  }

  render() {
    <div className="foo">
      <button onClick={this.goHome} />
    </div>
  }
}

export default withRouter(Foo)

9
Điều này làm việc cho tôi và có vẻ như giải pháp đơn giản nhất.
Rubycut

5
Đây là giải pháp tốt nhất. Tôi không hiểu tại sao nó có quá ít phiếu.
Benoit

1
có, bạn có thể nhấp vào liên kết vài lần và trình duyệt sẽ không hoạt động. bạn sẽ cần nhấp vào trình duyệt trở lại một vài lần để thực sự quay lại
Vladyslav Tereshyn

@VladyslavTereshyn bạn có thể thêm một số logic có điều kiện: if ((this.props.location.pathname + this.props.location.search)! ==
navigationToPath

15

Trong phiên bản 5.x , bạn có thể sử dụng useHistoryhook của react-router-dom:

// Sample extracted from https://reacttraining.com/react-router/core/api/Hooks/usehistory
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>
  );
}

Đây là giải pháp tốt nhất. Nếu bạn thêm một số logic có điều kiện, bạn có thể tránh các mục trùng lặp trong lịch sử khi người dùng nhấp vào cùng một nút nhiều lần:if ((routerHistory.location.pathname + routerHistory.location.search) !== navigateToPath) { routerHistory.push(navigateToPath); }
Mattweiler

Tôi cần phải khai báo historybiến, việc gọi thư mục useHistory().pushkhông được phép bởi các quy tắc hook
onmyway133

đây có vẻ là giải pháp phản ứng hiện đại nhất.
Youngjae

8

https://github.com/rackt/react-router/blob/bf89168acb30b6dc9b0244360bcbac5081cf6b38/examples/transitions/app.js#L50

hoặc thậm chí bạn có thể thử thực hiện onClick này (giải pháp bạo lực hơn):

window.location.assign("/sample");

Khi các dòng mã thay đổi, câu trả lời của bạn sẽ tốt hơn nếu bạn sao chép chi tiết và giải thích câu trả lời của bạn ở đây. Ngoài ra, assignkhông phải là một tài sản, nó là một chức năng.
WiredPrairi

(Nhưng bạn vẫn chỉ có một liên kết đến một dòng cụ thể của một tệp). Vui lòng bao gồm gợi ý cụ thể trong câu trả lời của bạn, và không chỉ là một liên kết.
WiredPrairi

Cảm ơn câu trả lời của bạn @grechut. Tuy nhiên, tôi muốn chắc chắn rằng Document hoàn toàn không biết gì về bộ định tuyến. Hành vi tôi mong đợi là: 'Nếu người dùng nhấp vào mũi tên phải, hãy gọi chức năng tiếp theo'. Các chức năng tiếp theo có thể là một liên kết hoặc không.
Alan Souza

Tôi có một vài trang được xử lý bên ngoài React (màn hình đăng nhập với chuyển hướng FB và Google) vì vậy tôi cần điều này trong điều hướng cho các trang đó kể từ "browserHistory.push ('/ home');" chỉ thay đổi URL, nó không thể định tuyến các trang. Cảm ơn bạn.
Deborah

7
Điều này sẽ tải lại trang @grechut, không phải là hành vi mong muốn cho một ứng dụng có bộ định tuyến phản ứng.
Abhas

2

Ok, tôi nghĩ rằng tôi đã có thể tìm ra một giải pháp thích hợp cho điều đó.

Bây giờ, thay vì gửi <Link/>dưới dạng prop đến Document, tôi gửi<NextLink/> đó là một trình bao bọc tùy chỉnh cho Liên kết bộ định tuyến phản ứng. Bằng cách đó, tôi có thể có mũi tên bên phải như một phần của cấu trúc Liên kết trong khi vẫn tránh để có mã định tuyến bên trong đối tượng Tài liệu.

Mã cập nhật trông như sau:

//in NextLink.js
var React = require('react');
var Right = require('./Right');

var NextLink = React.createClass({
    propTypes: {
        link: React.PropTypes.node.isRequired
    },

    contextTypes: {
        transitionTo: React.PropTypes.func.isRequired
    },

    _onClickRight: function() {
        this.context.transitionTo(this.props.link.props.to);
    },

    render: function() {
        return (
            <div>
                {this.props.link}
                <Right onClick={this._onClickRight} />
            </div>  
        );
    }
});

module.exports = NextLink;

...
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
var nextLink = <NextLink link={sampleLink} />
<Document next={nextLink} />

//in Document.js
...
var Document = React.createClass({
   render: function() {
      return (
         ...
         <div>{this.props.next}</div>
         ...
      );
   }
});
...

PS : Nếu bạn đang sử dụng phiên bản mới nhất của bộ định tuyến phản ứng, bạn có thể cần phải sử dụng this.context.router.transitionTothay vì this.context.transitionTo. Mã này sẽ hoạt động tốt cho phiên bản bộ định tuyến phản ứng 0.12.X.


2

Bộ định tuyến phản ứng 4

Bạn có thể dễ dàng gọi phương thức đẩy qua ngữ cảnh trong v4:

this.context.router.push(this.props.exitPath);

bối cảnh là:

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

Sử dụng BrowserRouter, đối tượng bối cảnh của các thành phần của tôi không chứa một routerđối tượng. Tôi có làm gì sai không?
pilau

Bạn đang thiết lập bối cảnh trong thành phần (khối thứ hai ở trên)?
Chris

Cảm ơn cho chiming trong! cuối cùng điều này làm việc cho tôi : router: React.PropTypes.object.isRequired. Tôi không biết tại sao nó không hoạt động mà không có isRequiredchìa khóa. Ngoài ra, <Link>dường như có thể có được historybối cảnh, nhưng tôi không thể sao chép nó.
pilau

Điều thú vị - nếu bạn đặt một codepen tôi có thể giúp bạn gỡ lỗi nếu bạn vẫn bị mắc kẹt
Chris

Có vẻ như bạn có thể sử dụng this.props.history.push()trong React Router v4. Tôi chỉ tìm thấy điều này bằng cách kiểm tra các đạo cụ mà React Router đi qua mặc dù. Nó dường như hoạt động nhưng tôi không chắc đó có phải là một ý tưởng tốt hay không.
sean_j_roberts

-1

một lần nữa đây là JS :) cái này vẫn hoạt động ....

var linkToClick = document.getElementById('something');
linkToClick.click();

<Link id="something" to={/somewhaere}> the link </Link>
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.