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>
         ...
      );
   }
});
...
Alan Souza
sumber

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

Matt Lo
sumber
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)
aw04
sumber
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>
  );
}
Paulo Mateus
sumber
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");
Grechut
sumber
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.

Alan Souza
sumber
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,
};
Chris
sumber
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>
taggartJ
sumber