React-router: Bagaimana cara mengaktifkan Link secara manual?


131

Saya baru mengenal ReactJS dan React-Router. Saya memiliki komponen yang menerima melalui alat peraga <Link/>objek dari react-router . Setiap kali pengguna mengklik tombol 'next' di dalam komponen ini saya ingin memanggil <Link/>objek secara manual.

Saat ini, saya menggunakan referensi untuk mengakses contoh dukungan dan secara manual mengklik tag 'a' yang <Link/>dihasilkan.

Pertanyaan: Apakah ada cara untuk secara manual menjalankan Tautan (mis. this.props.next.go)?

Ini adalah kode saat ini yang saya miliki:

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

Ini adalah kode yang saya ingin miliki:

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

Jawaban:


199

React Router v4 - Redirect Component (diperbarui 2017/04/15)

Cara v4 yang disarankan adalah membiarkan metode render Anda menangkap pengalihan. Gunakan status atau properti untuk menentukan apakah komponen pengalihan perlu ditampilkan (yang kemudian memicu pengalihan).

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

Referensi: https://reacttraining.com/react-router/web/api/Redirect

React Router v4 - Konteks Konteks Referensi

Anda juga dapat memanfaatkan Routerkonteks yang terpapar komponen Bereaksi.

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

Beginilah cara <Redirect />kerjanya di bawah tenda.

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

React Router v4 - Mutasi Object History Secara Eksternal

Jika Anda masih perlu melakukan sesuatu yang mirip dengan implementasi v2, Anda dapat membuat salinan BrowserRouterlalu mengeksposnya historysebagai konstanta yang dapat diekspor. Di bawah ini adalah contoh dasar tetapi Anda dapat membuatnya untuk menyuntikkannya dengan alat peraga yang dapat disesuaikan jika diperlukan. Ada peringatan yang dicatat dengan siklus hidup, tetapi itu harus selalu rerender Router, seperti di v2. Ini dapat berguna untuk pengalihan setelah permintaan API dari fungsi tindakan.

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

Terbaru BrowserRouteruntuk memperpanjang: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js

React Router v2

Dorong status baru ke browserHistoryinstance:

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

Referensi: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md


7
hashHistory.push ('/ sample'); jika Anda menggunakan hashHistory sebagai ganti browserHistory
sanath_p

1
ini sangat berguna dalam pustaka material-ui karena menggunakan containerElement = {<Tautan ke = "/" />} tidak selalu memunculkan tautan
Vishal Disawar

2
Catatan dengan opsi pengalihan Anda harus menentukan push (yaitu <Redirect push />). Secara default ia akan melakukan penggantian yang sama sekali tidak sama dengan secara manual menggunakan Tautan
aw04

1
@jokab Anda dapat menggunakan <NavLink /> alih-alih <Link /> github.com/ReactTraining/react-router/blob/master/packages/…
Matt Lo

1
Redirect tidak berfungsi untuk saya, tetapi solusi aw04 dengan withRouter lebih sederhana dan berfungsi
stackdave

90

React Router 4 menyertakan withRouter HOC yang memberi Anda akses ke historyobjek melalui 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
Ini bekerja untuk saya dan sepertinya solusi paling sederhana.
Rubycut

5
Ini solusi terbaik. Saya tidak mengerti mengapa ia memiliki sedikit suara.
Benoit

1
ya, Anda dapat mengklik tautan beberapa kali dan kembali browser tidak berfungsi. Anda harus mengklik kembali browser beberapa kali untuk benar-benar kembali
Vladyslav Tereshyn

@VladyslavTereshyn Anda dapat menambahkan beberapa logika kondisional: if ((this.props.location.pathname + this.props.location.search)! == navigToPath) {...}
MattWeiler

15

Di versi 5.x , Anda dapat menggunakan useHistorykait 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>
  );
}

Ini solusi terbaik. Jika Anda menambahkan beberapa logika kondisional, Anda dapat menghindari entri duplikat dalam riwayat ketika pengguna mengklik tombol yang sama beberapa kali:if ((routerHistory.location.pathname + routerHistory.location.search) !== navigateToPath) { routerHistory.push(navigateToPath); }
MattWeiler

Saya perlu mendeklarasikan historyvariabel, memohon direktori useHistory().pushtidak diizinkan oleh aturan kait
onmyway133

ini sepertinya solusi reaksi paling modern.
Youngjae

8

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

atau Anda bahkan dapat mencoba menjalankan onClick this (solusi yang lebih keras):

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

Saat baris kode berubah, jawaban Anda akan lebih baik jika Anda menyalin detail dan menjelaskan jawaban Anda di sini. Juga, assignbukan properti, itu fungsi.
WiredPrairie

(Tapi Anda masih memiliki tautan ke baris file tertentu). Harap sertakan saran spesifik dalam jawaban Anda, dan bukan hanya tautan.
WiredPrairie

Terima kasih atas jawaban Anda @grechut. Namun, saya ingin memastikan Dokumen tidak tahu apa-apa tentang router sama sekali. Perilaku yang saya harapkan adalah: 'Jika pengguna mengklik panah kanan, aktifkan fungsi berikutnya'. Fungsi selanjutnya bisa berupa tautan atau tidak.
Alan Souza

Saya memiliki beberapa halaman yang ditangani di luar React (layar masuk dengan pengalihan FB dan Google) jadi saya memerlukan ini di nav untuk halaman tersebut sejak "browserHistory.push ('/ home');" hanya mengubah URL, tidak dapat merutekan halaman. Terima kasih.
Deborah

7
Ini akan memuat ulang halaman @grechut, bukan perilaku yang diinginkan untuk aplikasi dengan router reaksi.
Abhas

2

Ok, saya pikir saya bisa menemukan solusi yang tepat untuk itu.

Sekarang, alih-alih mengirim <Link/>sebagai penyokong ke Dokumen, saya mengirim <NextLink/>yang merupakan pembungkus khusus untuk Tautan router reaksi. Dengan melakukan itu, saya dapat memiliki panah kanan sebagai bagian dari struktur Link sambil tetap menghindari memiliki kode perutean di dalam objek Dokumen.

Kode yang diperbarui terlihat seperti berikut:

//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 : Jika Anda menggunakan versi terbaru dari router reaksi Anda mungkin perlu menggunakan this.context.router.transitionTosebagai gantinya this.context.transitionTo. Kode ini akan berfungsi dengan baik untuk react-router versi 0.12.X.


2

Bereaksi Router 4

Anda dapat dengan mudah memanggil metode push melalui konteks di v4:

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

dimana konteksnya adalah:

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

Menggunakan BrowserRouter, objek konteks komponen saya tidak mengandung routerobjek. Apakah saya melakukan sesuatu yang salah?
pilau

Apakah Anda mengatur konteks dalam komponen (blok kedua di atas)?
Chris

Terima kasih sudah ikut! akhirnya ini bekerja untuk saya: router: React.PropTypes.object.isRequired. Saya tidak tahu mengapa itu tidak berhasil tanpa isRequiredkunci. Juga, <Link>tampaknya bisa mendapatkan historykonteksnya, tetapi saya tidak bisa meniru itu.
pilau

Yang menarik - jika Anda memasang codepen saya bisa membantu Anda men-debug-nya jika Anda masih macet
Chris

Sepertinya Anda dapat menggunakan this.props.history.push()React Router v4. Saya hanya menemukan ini dengan memeriksa alat peraga yang React Router lewat. Tampaknya bekerja tetapi saya tidak yakin apakah itu ide yang bagus.
sean_j_roberts

-1

sekali lagi ini JS :) ini masih berfungsi ....

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

<Link id="something" to={/somewhaere}> the link </Link>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.