Pertanyaan Navigasikan secara terprogram menggunakan router reaksi


Dengan react-router Saya bisa menggunakan Link elemen untuk membuat tautan yang secara asli ditangani oleh router yang bereaksi.

Saya melihat secara internal panggilan itu this.context.transitionTo(...).

Saya ingin melakukan navigasi, tetapi tidak dari tautan, dari pilihan tarik-turun misalnya. Bagaimana saya bisa melakukan ini dalam kode? apa yang this.context?

Saya melihat Navigation mixin, tetapi bisakah saya melakukan ini tanpa mixin?


775
2018-06-26 17:38


asal


Jawaban:


Bereaksi Router v4

Dengan v4 React Router, ada tiga pendekatan yang dapat Anda ambil untuk memprogram routing dalam komponen.

  1. Menggunakan withRouter komponen pesanan yang lebih tinggi.
  2. Gunakan komposisi dan render a <Route>
  3. Menggunakan context.

React Router sebagian besar merupakan pembungkus di sekitar history Perpustakaan. history menangani interaksi dengan browser window.history untuk Anda dengan browser dan riwayat hashnya. Ini juga menyediakan riwayat memori yang berguna untuk lingkungan yang tidak memiliki sejarah global. Ini sangat berguna dalam pengembangan aplikasi seluler (react-native) dan pengujian unit dengan Node.

SEBUAH history instance memiliki dua metode untuk menavigasi: push dan replace. Jika Anda memikirkan history sebagai larik lokasi yang dikunjungi, push akan menambahkan lokasi baru ke array dan replace akan menggantikan lokasi saat ini dalam larik dengan yang baru. Biasanya Anda akan ingin menggunakan push metode saat Anda menavigasi.

Pada versi React Router sebelumnya, Anda harus membuatnya sendiri history Misalnya, tetapi di v4 yang <BrowserRouter>, <HashRouter>, dan <MemoryRouter> komponen akan membuat browser, hash, dan instance memori untuk Anda. Bereaksi Router membuat sifat dan metode dari history Instance yang terkait dengan router Anda tersedia melalui konteks, di bawah router obyek.

1. Gunakan withRouter komponen pesanan yang lebih tinggi

Itu withRouter komponen yang lebih tinggi akan menyuntikkan history objek sebagai penyangga komponen. Ini memungkinkan Anda untuk mengakses push dan replace metode tanpa harus berurusan dengan 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. Gunakan komposisi dan render a <Route>

Itu <Route> komponen tidak hanya untuk lokasi yang cocok. Anda dapat membuat rute tanpa jalur dan itu akan selalu cocok dengan lokasi saat ini. Itu <Route> komponen melewati alat peraga yang sama seperti withRouter, sehingga Anda akan dapat mengakses history metode melalui history menopang.

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

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

3. Gunakan konteksnya *

* Tetapi Anda mungkin tidak seharusnya

Opsi terakhir adalah opsi yang sebaiknya hanya digunakan jika Anda merasa nyaman bekerja dengan React's konteks model. Meskipun konteks adalah pilihan, harus ditekankan bahwa konteks adalah API yang tidak stabil dan React memiliki bagian Mengapa Tidak Menggunakan Konteks dalam dokumentasi mereka. Jadi gunakan dengan resiko Anda sendiri!

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 dan 2 adalah pilihan paling sederhana untuk diterapkan, jadi untuk sebagian besar kasus penggunaan, mereka adalah taruhan terbaik Anda.


614
2018-02-08 18:39



React-Router 4.0.0+ Menjawab

Dalam 4.0 dan di atas, gunakan sejarah sebagai penyangga komponen Anda.

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

React-Router 3.0.0+ Menjawab

Dalam 3.0 dan di atas, gunakan router sebagai penyangga komponen Anda.

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

React-Router 2.4.0+ Menjawab

Dalam 2.4 dan di atas, gunakan komponen pesanan yang lebih tinggi untuk mendapatkan router sebagai penyangga komponen Anda.

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

React-Router 2.0.0+ Menjawab

Versi ini kompatibel dengan 1.x sehingga tidak perlu Panduan Upgrade. Hanya melalui contoh-contoh saja seharusnya sudah cukup baik.

Yang mengatakan, jika Anda ingin beralih ke pola baru, ada modul browserHistory di dalam router yang dapat Anda akses

import { browserHistory } from 'react-router'

Sekarang Anda memiliki akses ke riwayat browser Anda, sehingga Anda dapat melakukan hal-hal seperti push, ganti, dll ... Seperti:

browserHistory.push('/some/path')

Bacaan lebih lanjut: Sejarah dan Navigasi


Bereaksi-Router 1.x.x Menjawab

Saya tidak akan membahas detail peningkatan. Anda dapat membaca tentang itu di Panduan Upgrade

Perubahan utama tentang pertanyaan di sini adalah perubahan dari Mixin Navigasi ke Riwayat. Sekarang ini menggunakan riwayat browserAPI untuk mengubah rute sehingga kami akan menggunakan pushState() dari sekarang.

Berikut contoh menggunakan Mixin:

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

Perhatikan bahwa ini History datang dari rakt / sejarah proyek. Bukan dari React-Router sendiri.

Jika Anda tidak ingin menggunakan Mixin untuk beberapa alasan (mungkin karena kelas ES6), maka Anda dapat mengakses riwayat yang Anda dapatkan dari router dari this.props.history. Ini hanya dapat diakses untuk komponen yang diberikan oleh Router Anda. Jadi, jika Anda ingin menggunakannya di setiap komponen anak, itu harus diwariskan sebagai atribut melalui props.

Anda dapat membaca lebih lanjut tentang rilis baru di mereka Dokumentasi 1.0.x

Disini adalah halaman bantuan khusus tentang navigasi di luar komponen Anda

Ini merekomendasikan mengambil referensi history = createHistory() dan menelepon replaceState tentang itu.

React-Router 0.13.x Menjawab

Saya mengalami masalah yang sama dan hanya dapat menemukan solusi dengan mixin Navigasi yang dilengkapi dengan re-router.

Begini cara saya melakukannya

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

Saya bisa menelepon transitionTo() tanpa perlu akses .context

Atau Anda bisa mencoba ES6 yang mewah 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
};

Bereaksi-Router-Redux

catatan: jika Anda menggunakan Redux, ada proyek lain yang disebut    Bereaksi-Router-Redux yang memberi Anda   redux bindings untuk ReactRouter, menggunakan pendekatan yang agak sama itu    Bereaksi-Redux tidak

React-Router-Redux memiliki beberapa metode yang tersedia yang memungkinkan navigasi sederhana dari pembuat tindakan di dalam. Ini dapat sangat berguna bagi orang yang memiliki arsitektur di React Native, dan mereka ingin memanfaatkan pola yang sama di React Web dengan overhead boilerplate minimal.

Jelajahi metode berikut:

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

Berikut ini contoh penggunaan, dengan 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>

662
2018-06-26 17:49



React-Router v2

Untuk rilis terbaru (v2.0.0-rc5), metode navigasi yang disarankan adalah dengan langsung mendorong ke riwayat tunggal. Anda dapat melihat bahwa dalam aksi di Menavigasi di luar dokumen Komponen.

Kutipan yang relevan:

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

Jika menggunakan API reaksi router yang lebih baru, Anda harus menggunakan historydari this.props ketika di dalam komponen jadi:

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

Ini juga menawarkan pushState tetapi itu tidak berlaku per peringatan login.

Jika menggunakan react-router-redux, ia menawarkan sebuah push fungsi yang dapat Anda kirim seperti ini:

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

Namun ini mungkin hanya digunakan untuk mengubah URL, bukan untuk benar-benar menavigasi ke halaman.


466
2018-01-18 20:32



Beginilah cara Anda melakukan ini react-router v2.0.0 dengan ES6. react-router telah pindah dari mixins.

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
}

34
2018-01-22 20:46



Untuk yang ini, yang tidak mengontrol sisi server dan karena ini menggunakan hash router v2:

Tempatkan Anda sejarah ke dalam file terpisah (mis. app_history.js ES6):

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

export default appHistory;

Dan gunakan di mana-mana!

Titik masuk Anda untuk router reaksi (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"]'));

Navigasi Anda di dalam komponen apa pun (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()
  }
})

25
2018-03-19 12:59



React-Router 4.x Answer:

Pada akhirnya, saya ingin memiliki objek sejarah tunggal yang dapat saya bawa bahkan di luar komponen. Yang saya suka lakukan adalah memiliki file history.js tunggal yang saya impor sesuai permintaan, dan hanya memanipulasinya.

Anda hanya perlu berubah BrowserRouter ke Router, dan tentukan prop sejarah. Ini tidak mengubah apa pun untuk Anda kecuali bahwa Anda memiliki objek sejarah Anda sendiri yang dapat Anda manipulasi seperti yang Anda inginkan.

Anda perlu menginstal sejarah, perpustakaan yang digunakan oleh react-router.

Contoh penggunaan, notasi 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>;
    }
}

EDIT 16 April 2018:

Jika Anda harus menavigasi dari komponen yang benar-benar diberikan dari Route komponen, Anda juga dapat mengakses riwayat dari properti, seperti itu:

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

20
2018-06-06 22:14



PERINGATAN: Jawaban ini hanya mencakup versi ReactRouter sebelum 1.0

Saya akan memperbarui jawaban ini dengan kasus penggunaan 1.0.0-rc1 setelah!

Anda dapat melakukan ini tanpa mixins juga.

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

The gotcha dengan konteks adalah bahwa itu tidak dapat diakses kecuali Anda mendefinisikan contextTypes di kelas.

Adapun apa konteksnya, itu adalah objek, seperti alat peraga, yang diturunkan dari orang tua ke anak, tetapi diwariskan secara implisit, tanpa harus menyarang ulang alat peraga setiap waktu. Lihat https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html


19
2018-06-30 06:14



Saya mencoba setidaknya 10 cara melakukan ini sebelum sesuatu bekerja dengan baik!

@Felipe Skinner withRouter Jawabannya agak membingungkan saya, dan saya tidak yakin saya ingin membuat nama kelas baru "ExportedWithRouter".

Inilah cara termudah dan terbersih untuk melakukannya, sekitar React-Router 3.0.0 dan ES6 saat ini:

React-Router 3.x.x dengan 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);

atau, jika bukan kelas default Anda, ekspor seperti:

withRouter(Example);
export { Example };

Perhatikan bahwa dalam 3.x.x, <Link> komponen itu sendiri menggunakan router.push, sehingga Anda dapat lulus apa pun yang Anda akan lulus <Link to= tag, seperti:

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'

15
2017-11-30 14:02



Untuk komponen ES6 + React, solusi berikut berhasil untuk saya.

Saya mengikuti Felippe skinner, tetapi menambahkan solusi ujung ke ujung untuk membantu pemula seperti saya.

Di bawah ini adalah versi yang saya gunakan:

"react-router": "^ 2.7.0"

"bereaksi": "^ 15.3.1"

Di bawah ini adalah komponen reaksi saya di mana saya menggunakan navigasi terprogram menggunakan react-router:

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;

Di bawah ini adalah konfigurasi untuk router saya:

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

11
2017-09-12 22:00