Navigasi terprogram menggunakan router reaksi V4

336

Saya baru saja mengganti react-routerdari v3 ke v4.
Tetapi saya tidak yakin bagaimana cara menavigasi secara terprogram dalam fungsi anggota a Component. yaitu dalam handleClick()fungsi saya ingin menavigasi ke /path/some/wheresetelah memproses beberapa data. Saya biasa melakukannya dengan:

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

Tapi saya tidak dapat menemukan antarmuka seperti itu di v4.
Bagaimana saya bisa bernavigasi menggunakan v4?

Colin Witkamp
sumber
3
Anda dapat mengakses objek sejarah di v4 melalui alat peraga: this.props.history.push ('/')
colemerrick
6
Bagaimana jika Anda ingin mengaksesnya dari tempat yang berbeda dari Component? Misalnya, di dalam tindakan redux.
Maximus S
73
kadang-kadang saya bertanya-tanya mengapa begitu rumit untuk hanya berpindah dari satu tautan ke yang lain =))
Thai Tran
12
Orang akan berpikir bahwa di zaman sekarang ini pengarahan ulang tidak akan terlalu rumit.
JohnAllen
Saya menemukan posting ini bermanfaat: medium.com/@anneeb/redirecting-in-react-4de5e517354a
BioData41

Jawaban:

414

Jika Anda menargetkan lingkungan browser, Anda harus menggunakan react-router-dompaket, bukan react-router. Mereka mengikuti pendekatan yang sama seperti React, untuk memisahkan inti, ( react) dan kode khusus platform, ( react-dom, react-native) dengan perbedaan halus yang Anda tidak perlu menginstal dua paket terpisah, sehingga paket lingkungan berisi semuanya kamu membutuhkan. Anda dapat menambahkannya ke proyek Anda sebagai:

yarn add react-router-dom

atau

npm i react-router-dom

Hal pertama yang perlu Anda lakukan adalah menyediakan <BrowserRouter>komponen induk paling top dalam aplikasi Anda. <BrowserRouter>menggunakan historyAPI HTML5 dan mengaturnya untuk Anda, jadi Anda tidak perlu khawatir tentang instantiasi sendiri dan meneruskannya ke<BrowserRouter> komponen sebagai penyangga (seperti yang perlu Anda lakukan di versi sebelumnya).

Di V4, untuk bernavigasi secara terprogram Anda perlu mengakses historyobjek, yang tersedia melalui React context, selama Anda memiliki komponen <BrowserRouter> penyedia sebagai orang tua paling top dalam aplikasi Anda. Perpustakaan memperlihatkan melalui konteks routerobjek, yang berisi historysebagai properti. The historyantarmuka menawarkan beberapa metode navigasi, seperti push, replacedan goBack, antara lain. Anda dapat memeriksa seluruh daftar properti dan metode di sini .

Catatan Penting untuk pengguna Redux / Mobx

Jika Anda menggunakan redux atau mobx sebagai pustaka manajemen negara Anda di aplikasi Anda, Anda mungkin telah menemukan masalah dengan komponen yang harus sadar lokasi tetapi tidak dirender kembali setelah memicu pembaruan URL

Itu terjadi karena react-routerberalih locationke komponen menggunakan model konteks.

Baik connect dan observer membuat komponen yang metode shouldComponentUpdate melakukan perbandingan yang dangkal dari alat peraga mereka saat ini dan alat peraga berikutnya. Komponen-komponen itu hanya akan merender ulang jika setidaknya satu penyangga telah berubah. Ini berarti bahwa untuk memastikan mereka memperbarui ketika lokasi berubah, mereka akan perlu diberi properti yang berubah ketika lokasi berubah.

2 pendekatan untuk menyelesaikan ini adalah:

  • Bungkus komponen Anda yang terhubung dalam jalur <Route />. locationObjek saat ini adalah salah satu alat peraga yang <Route>dilewatkan ke komponen yang direndernya
  • Bungkus komponen Anda yang terhubung dengan komponen tingkat withRoutertinggi, yang sebenarnya memiliki efek yang sama dan menyuntikkan locationsebagai penyangga

Selain itu, ada empat cara untuk bernavigasi secara terprogram, diurutkan berdasarkan rekomendasi:

1.- Menggunakan <Route>Komponen

Ini mempromosikan gaya deklaratif. Sebelum v4, <Route />komponen ditempatkan di bagian atas hirarki komponen Anda, harus memikirkan struktur rute Anda sebelumnya. Namun, sekarang Anda dapat memiliki <Route>komponen di mana saja di pohon Anda, memungkinkan Anda untuk memiliki kontrol yang lebih baik untuk rendering bersyarat tergantung pada URL. Routemenyuntikkan match, locationdan historysebagai penyangga ke komponen Anda. Metode navigasi (seperti push, replace, goBack...) yang tersedia sebagai properti dari historyobjek.

Ada 3 cara untuk membuat sesuatu dengan Route, dengan menggunakan salah satu component, renderatau childrenalat peraga, tetapi jangan gunakan lebih dari satu cara yang sama Route. Pilihannya tergantung pada kasus penggunaan, tetapi pada dasarnya dua opsi pertama hanya akan membuat komponen Anda jika pathcocok dengan lokasi url, sedangkan dengan childrenkomponen akan ditampilkan apakah jalur cocok dengan lokasi atau tidak (berguna untuk menyesuaikan UI berdasarkan URL) sesuai).

Jika Anda ingin menyesuaikan output rendering komponen Anda, Anda perlu membungkus komponen Anda dalam suatu fungsi dan menggunakan renderopsi, untuk meneruskan ke komponen Anda alat peraga lain yang Anda inginkan, terlepas dari match, locationdan history. Contoh untuk menggambarkan:

import { BrowserRouter as Router } from 'react-router-dom'

const ButtonToNavigate = ({ title, history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    {title}
  </button>
);

const SomeComponent = () => (
  <Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)    

const App = () => (
  <Router>
    <SomeComponent /> // Notice how in v4 we can have any other component interleaved
    <AnotherComponent />
  </Router>
);

2.- Menggunakan withRouterHoC

Komponen pesanan lebih tinggi ini akan menyuntikkan alat peraga yang sama dengan Route. Namun, ia membawa batasan bahwa Anda hanya dapat memiliki 1 HoC per file.

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

const ButtonToNavigate = ({ history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    Navigate
  </button>
);


ButtonToNavigate.propTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired,
  }),
};

export default withRouter(ButtonToNavigate);

3.- Menggunakan Redirectkomponen

Rendering a <Redirect>akan menavigasi ke lokasi baru. Namun perlu diingat bahwa, secara default , lokasi saat ini diganti dengan yang baru, seperti pengalihan sisi-server (HTTP 3xx). Lokasi baru disediakan oleh toprop, yang bisa berupa string (URL untuk dialihkan ke) atau locationobjek. Jika Anda ingin memasukkan entri baru ke histori , lewati juga pushprop dan aturtrue

<Redirect to="/your-new-location" push />

4.- Mengakses routersecara manual melalui konteks

Sedikit berkecil hati karena konteksnya masih merupakan API eksperimental dan kemungkinan akan pecah / berubah dalam rilis React di masa depan

const ButtonToNavigate = (props, context) => (
  <button
    type="button"
    onClick={() => context.router.history.push('/my-new-location')}
  >
    Navigate to a new location
  </button>
);

ButtonToNavigate.contextTypes = {
  router: React.PropTypes.shape({
    history: React.PropTypes.object.isRequired,
  }),
};

Tak perlu dikatakan ada juga komponen Router lain yang dimaksudkan untuk ekosistem non browser, seperti <NativeRouter>yang mereplikasi tumpukan navigasi dalam memori dan target platform React Native, tersedia melalui react-router-nativepaket.

Untuk referensi lebih lanjut, jangan ragu untuk melihat dokumen resmi . Ada juga video yang dibuat oleh salah satu penulis perpustakaan yang memberikan pengantar yang cukup keren untuk bereaksi-router v4, menyoroti beberapa perubahan besar.

rgommezz
sumber
2
Saya menggunakan V4 dan di atas berfungsi dengan baik. Saya telah menghabiskan sedikit waktu mucking tentang dengan router V4 karena tampaknya ada beberapa pilihan aneh tetapi di atas pasti berhasil. Saya berasumsi Anda mengimpor withRouterdarireact-router-dom
Sam Parmenter
3
Saya mengimpor withRouterdari react-router-dom. History.push memang mengubah url, tetapi sepertinya tidak memuat <Route>sampai saya memaksakan menyegarkan laman ...
BreakDS
1
@rauliyohmc saya salah tentang ini. Masalahnya adalah bahwa saya memiliki <Router> di dalam komponen Bereaksi yang dihiasi dengan @observer, yang memicu masalah ini . Pekerjaan di sekitar adalah untuk memiliki @withRouterpada setiap komponen Bereaksi tersebut.
BreakDS
3
Bagi mereka yang menemukan jawaban hebat ini, withRouterhanyalah HOC yang menggunakan Routeunder hood. Yang berarti hanya menggunakan 3 alat peraga, riwayat, kecocokan, dan lokasi . Pada contoh di atas tampak bahwa itu pushadalah prop yang withRouterakan ditambahkan ButtonToNavigate, tetapi bukan itu masalahnya. props.history.pushharus digunakan sebagai gantinya. Semoga ini bisa membantu orang lain yang agak bingung.
vinnymac
39
Wow. browserHistory.push('/path/some/where')sepertinya jauh lebih sederhana. Para penulis mencoba untuk mencegah pemrograman imperatif, tetapi kadang-kadang hanya berfungsi lebih baik!
lux
149

Cara termudah untuk menyelesaikannya:

this.props.history.push("/new/url")

catatan:

  • Anda mungkin ingin meneruskan history propdari komponen induk ke komponen yang ingin Anda panggil tindakan jika tidak tersedia.
Jikku Jose
sumber
10
Saya menggunakan router 4.0, tetapi tidak ada kunci sejarah pada alat peraga. Bagaimana saya bisa memperbaikinya?
Nicolas S.Xu
41
Jika Anda tidak memiliki this.props.historytersedia di komponen Anda maka Anda dapat import {withRouter} from 'react-router-dom'dan kemudian export default withRouter(MyComponent)(atau const MyComponent = withRouter(...)) dan itu akan memasukkan historyitem dalam alat peraga komponen Anda.
Malvineous
@Malvineous itu menarik, tidak tahu tentang ini! Akan mencobanya!
Jikku Jose
2
Saya harus kehilangan sesuatu yang mendasar, karena ini bekerja sangat baik bagi saya jadi saya tidak tahu mengapa semua jawaban membutuhkan penjelasan yang panjang.
Joshua Pinter
bagaimana mencegah remount komponen history.pushdan hanya memicu pembaruan seperti ketika kita mengklik<Link>
Rahul Yadav
55

Saya memiliki masalah serupa ketika bermigrasi ke React-Router v4 jadi saya akan mencoba menjelaskan solusi saya di bawah ini.

Tolong jangan menganggap jawaban ini sebagai cara yang tepat untuk menyelesaikan masalah, saya membayangkan ada peluang bagus sesuatu yang lebih baik akan muncul karena React Router v4 menjadi lebih matang dan meninggalkan beta (Bahkan mungkin sudah ada dan saya tidak menemukannya) .

Untuk konteks, saya punya masalah ini karena saya kadang-kadang menggunakan Redux-Sagauntuk mengubah secara terprogram objek sejarah (katakanlah ketika pengguna berhasil mengotentikasi).

Dalam dokumen React Router, lihat <Router> komponennya dan Anda dapat melihat Anda memiliki kemampuan untuk melewati objek sejarah Anda sendiri melalui alat peraga. Ini adalah inti dari solusi - kami menyediakan objek sejarah untuk React-Routerdari dunia modul.

Langkah:

  1. Instal modul npm history - yarn add history atau npm install history --save
  2. buat file yang disebut history.jsdi App.jsfolder level Anda (ini adalah preferensi saya)

    // src/history.js
    
    import createHistory from 'history/createBrowserHistory';
    export default createHistory();`
  3. Tambahkan objek riwayat ini ke komponen Router Anda seperti itu

    // src/App.js
    
    import history from '../your/path/to/history.js;'
    <Router history={history}>
    // Route tags here
    </Router>
  4. Sesuaikan URL seperti sebelumnya dengan mengimpor objek riwayat global Anda :

    import history from '../your/path/to/history.js;'
    history.push('new/path/here/');

Semuanya harus tetap disinkronkan sekarang, dan Anda juga memiliki akses ke cara mengatur objek sejarah secara terprogram dan tidak melalui komponen / wadah.

Alex Mann
sumber
5
Perubahan ini berhasil bagi saya, tetapi hanya karena saya menavigasi di luar komponen. Jika saya menavigasi di dalam komponen seperti OP, saya akan menggunakan pendekatan yang disarankan oleh @rauliyohmc dengan menggunakan alat peraga yang diturunkan oleh Routekomponen.
Dan Ellis
2
ini adalah pendekatan yang direkomendasikan pada
08/17
2
@Spets Dalam kasus saya, jika saya menggunakan pendekatan semacam ini, tautan akan diperbarui dengan benar setelah push, tetapi komponen tidak ditampilkan dengan benar (misalnya, setelah memperbarui tautan, komponen tidak diperbarui kecuali Anda memaksakan penyegaran halaman). Di mana Anda menemukan bahwa ini adalah pendekatan yang disarankan? Adakah tautan / sumber?
keren
2
@ScottCoates Saya disortir menggunakan contoh di atas, memang dengan memberikan sejarah sebagai parameter, tetapi setelah saya melakukan debug modul simpul sendiri. Ada kesalahan umum yang terjadi di seluruh web, menggunakan impor "BrowserHistory as Router", ketika ada objek lain yang disebut Router dengan sendirinya dalam versi terbaru dari react-router-dom. Menggunakan itu dalam kombinasi dengan sejarah yang dibuat dalam contoh di atas berfungsi dengan baik.
keren
2
url diperbarui, tetapi halaman tersebut tidak renderd berdasarkan root baru. Ada solusi? Mengapa rute pemicu sangat sulit? Orang yang mendesain bereaksi keluar dari pikiran mereka?
Nicolas S.Xu
43

TL; DR:

if (navigate) {
  return <Redirect to="/" push={true} />
}

Jawaban sederhana dan deklaratif adalah bahwa Anda harus menggunakan <Redirect to={URL} push={boolean} />dalam kombinasi dengansetState()

push: boolean - ketika benar, pengalihan akan mendorong entri baru ke histori alih-alih menggantikan yang sekarang.


import { Redirect } from 'react-router'

class FooBar extends React.Component {
  state = {
    navigate: false
  }

  render() {
    const { navigate } = this.state

    // here is the important part
    if (navigate) {
      return <Redirect to="/" push={true} />
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^

    return (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}

Contoh lengkap di sini . Baca lebih lanjut di sini .

PS. Contohnya menggunakan ES7 + Properti Inisialisasi untuk menginisialisasi keadaan. Lihat di sini juga, jika Anda tertarik.

Lyubomir
sumber
5
Ini harus diterima jawaban. Solusi elegan paling sederhana! +1 untuk @lustoykov
Ali Abbas Jaffri
1
Saya juga mengatur navigasi kembali ke false di componentDidUpdate karena tombol saya ada di header dan jika tidak hanya akan menavigasi sekali.
peterorum
Ini hanya berfungsi jika Anda tahu tentang pengalihan ketika halaman dimuat. Jika Anda menunggu panggilan asinkron untuk kembali (yaitu otentikasi dengan Google atau sesuatu) maka Anda harus menggunakan salah satu history.push()metode.
brittohalloran
Tidak juga, Anda masih dapat memanfaatkan sifat deklaratif reaksi yang dikombinasikan dengan komponen <Redirect />. Jika halaman tidak memuat, Anda dapat mundur ke <Redirect /> lainnya
Lyubomir
@ brittohalloran ide metode ini menggunakan router reaksi yang tepat, adalah untuk memastikan Anda menggunakan setState untuk memaksa re-render.
Seseorang Spesial
16

Gunakan useHistorykait jika Anda menggunakan komponen fungsi

Anda dapat menggunakan useHistorykait untuk mendapatkan historycontoh.

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

const MyComponent = () => {
  var history = useHistory();

  return (
    <button onClick={() => history.push("/about")}>
      Click me
    </button>
  );
}

The useHistorykait memberikan Anda akses ke contoh sejarah yang mungkin Anda gunakan untuk menavigasi.

Gunakan historyproperti di dalam komponen halaman

React Router menyuntikkan beberapa properti termasuk historyke komponen halaman.

class HomePage extends React.Component {
  render() {
    const { history } = this.props;

    return (
      <div>
        <button onClick={() => history.push("/projects")}>
          Projects
        </button>
      </div>
    );
  }
}

Bungkus komponen anak withRouteruntuk menyuntikkan properti router

withRouterwrapper menyuntikkan properti router ke komponen. Misalnya Anda dapat menggunakan pembungkus ini untuk menyuntikkan router ke komponen tombol logout yang ditempatkan di dalam menu pengguna.

import { withRouter } from "react-router";

const LogoutButton = withRouter(({ history }) => {
  return (
    <button onClick={() => history.push("/login")}>
      Logout
    </button>
  );
});

export default LogoutButton;
TheMisir
sumber
11

Anda juga bisa menggunakan alat peraga untuk mengakses objek riwayat: this.props.history.push('new_url')

pengguna1445685
sumber
5
Berguna hanya ketika di komponen langsung turun dari Router. Supaya Anda tidak melewatkan prop sejarah ke setiap komponen yang Anda perlukan fungsi ini.
mwieczorek
3
Jika Anda tidak memiliki this.props.historytersedia di komponen Anda maka Anda dapat import {withRouter} from 'react-router-dom'dan kemudian export default withRouter(MyComponent)(atau const MyComponent = withRouter(...)) dan itu akan memasukkan historyitem dalam alat peraga komponen Anda.
Malvineous
9

Langkah 1: Hanya ada satu hal untuk diimpor di atas:

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

Langkah 2: Di Rute Anda, sampaikan riwayat:

<Route
  exact
  path='/posts/add'
  render={({history}) => (
    <PostAdd history={history} />
  )}
/>

Langkah 3: sejarah diterima sebagai bagian dari alat peraga di Komponen berikutnya, sehingga Anda dapat:

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

Itu mudah dan sangat kuat.

cdi-meo
sumber
7

Ini bekerja:

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

const SomeComponent = withRouter(({ history }) => (
    <div onClick={() => history.push('/path/some/where')}>
        some clickable element
    </div>); 
);

export default SomeComponent;
Kaya Toast
sumber
5

Jawaban saya mirip dengan jawaban Alex . Saya tidak yakin mengapa React-Router membuat ini sangat rumit. Mengapa saya harus membungkus komponen saya dengan HoC hanya untuk mendapatkan akses ke apa yang pada dasarnya global?

Lagi pula, jika Anda melihat bagaimana penerapannya <BrowserRouter>, itu hanya pembungkus kecil di sekitar sejarah .

Kami dapat menarik sejarah itu sehingga kami dapat mengimpornya dari mana saja. Kuncinya, bagaimanapun, adalah jika Anda melakukan rendering sisi server dan Anda mencoba importmodul histori, itu tidak akan berhasil karena menggunakan API khusus browser. Tapi tidak apa-apa karena kami biasanya hanya mengarahkan sebagai tanggapan terhadap klik atau acara sisi klien lainnya. Karena itu, boleh saja memalsukannya:

// history.js
if(__SERVER__) {
    module.exports = {};
} else {
    module.exports = require('history').createBrowserHistory();
}

Dengan bantuan webpack, kami dapat mendefinisikan beberapa vars sehingga kami tahu di lingkungan mana kita berada:

plugins: [
    new DefinePlugin({
        '__SERVER__': 'false',
        '__BROWSER__': 'true', // you really only need one of these, but I like to have both
    }),

Dan sekarang kamu bisa

import history from './history';

Dari mana-mana. Itu hanya akan mengembalikan modul kosong di server.

Jika Anda tidak ingin menggunakan magic vars ini, Anda hanya perlu berada requiredi objek global yang membutuhkannya (di dalam event handler Anda). importtidak akan berfungsi karena hanya berfungsi di tingkat atas.

Mpen
sumber
6
sialan mereka membuatnya sangat rumit.
Abhishek
4
Saya sangat setuju dengan Anda. ini sangat rumit hanya untuk navigasi
Thai Tran
5

Saya pikir @rgommezz mencakup sebagian besar kasus minus satu yang saya pikir cukup penting.

// history is already a dependency or React Router, but if don't have it then try npm install save-dev history

import createHistory from "history/createBrowserHistory"

// in your function then call add the below 
const history = createHistory();
// Use push, replace, and go to navigate around.
history.push("/home");

Ini memungkinkan saya untuk menulis layanan sederhana dengan tindakan / panggilan yang dapat saya panggil untuk melakukan navigasi dari komponen apa pun yang saya inginkan tanpa melakukan banyak HoC pada komponen saya ...

Tidak jelas mengapa tidak ada yang memberikan solusi ini sebelumnya. Saya harap ini membantu, dan jika Anda melihat masalah dengannya, beri tahu saya.

pengguna3053247
sumber
4

Saya telah menguji v4 selama beberapa hari sekarang dan .. Saya sangat menyukainya sejauh ini! Masuk akal setelah beberapa saat.

Saya juga memiliki pertanyaan yang sama dan saya menemukan penanganannya seperti yang berikut ini paling berhasil (dan bahkan mungkin seperti yang dimaksudkan). Ini menggunakan negara, operator ternary dan <Redirect>.

Dalam konstruktor ()

this.state = {
    redirectTo: null
} 
this.clickhandler = this.clickhandler.bind(this);

Di render ()

render(){
    return (
        <div>
        { this.state.redirectTo ?
            <Redirect to={{ pathname: this.state.redirectTo }} /> : 
            (
             <div>
               ..
             <button onClick={ this.clickhandler } />
              ..
             </div>
             )
         }

Di clickhandler ()

 this.setState({ redirectTo: '/path/some/where' });

Semoga ini bisa membantu. Biarkan aku tahu.

jar0m1r
sumber
Apakah ada jebakan dengan metode ini? Dalam proyek saya dengan bekerja hanya ketika saya menetapkan negara dalam konstruktor, dari sana saya dapat mengarahkan ulang ke halaman yang saya inginkan. Tetapi ketika saya mengatur keadaan pada acara (alat peraga memang berubah, misalnya) saya melihat metode render disebut dengan negara baru, tetapi pengalihan tidak terjadi saya melihat halaman yang sama
Dmitry Malugin
Pitfall adalah itu akan menggantikan sejarah, sehingga Anda tidak akan bisa membalas - jadi pada dasarnya, ini bukan solusi yang baik.
dannytenaglias
4

Saya berjuang dengan ini untuk sementara waktu - sesuatu yang sangat sederhana, namun sangat rumit, karena ReactJS hanyalah cara penulisan aplikasi web yang benar-benar berbeda, itu sangat asing bagi kami orang yang lebih tua!

Saya membuat komponen terpisah untuk abstrak kekacauan:

// LinkButton.js

import React from "react";
import PropTypes from "prop-types";
import {Route} from 'react-router-dom';

export default class LinkButton extends React.Component {

    render() {
        return (
            <Route render={({history}) => (
                <button {...this.props}
                       onClick={() => {
                           history.push(this.props.to)
                       }}>
                    {this.props.children}
                </button>
            )}/>
        );
    }
}

LinkButton.propTypes = {
    to: PropTypes.string.isRequired
};

Kemudian tambahkan ke render()metode Anda :

<LinkButton className="btn btn-primary" to="/location">
    Button Text
</LinkButton>
mwieczorek
sumber
Saya menemukan solusi ini cukup berguna. Saya menyalin kode. Biarkan saya tahu Anda meletakkannya di github - Saya akan langsung menghubungkannya dengan Anda.
Abhinav Manchanda
3

Karena tidak ada cara lain untuk menangani desain yang mengerikan ini, saya menulis komponen generik yang menggunakan pendekatan withRouter HOC . Contoh di bawah ini adalah membungkus buttonelemen, tetapi Anda dapat mengubah ke elemen yang dapat diklik yang Anda butuhkan:

import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';

const NavButton = (props) => (
  <Button onClick={() => props.history.push(props.to)}>
    {props.children}
  </Button>
);

NavButton.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func.isRequired
  }),
  to: PropTypes.string.isRequired
};

export default withRouter(NavButton);

Pemakaian:

<NavButton to="/somewhere">Click me</NavButton>
Rodrigo
sumber
3
this.props.history.push("/url")

Jika Anda belum menemukan this.props.history tersedia di komponen Anda, maka coba ini

import {withRouter} from 'react-router-dom'
export default withRouter(MyComponent)  
Shashwat Gupta
sumber
Terima kasih banyak!
QauseenMZ
1

Karena kadang-kadang saya lebih suka beralih rute dengan Aplikasi daripada dengan tombol, ini adalah contoh kerja minimal yang berfungsi untuk saya:

import { Component } from 'react'
import { BrowserRouter as Router, Link } from 'react-router-dom'

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

    /** @type BrowserRouter */
    this.router = undefined
  }

  async handleSignFormSubmit() {
    await magic()
    this.router.history.push('/')
  }

  render() {
    return (
      <Router ref={ el => this.router = el }>
        <Link to="/signin">Sign in</Link>
        <Route path="/signin" exact={true} render={() => (
          <SignPage onFormSubmit={ this.handleSignFormSubmit } />
        )} />
      </Router>
    )
  }
}
piotr_cz
sumber
0

Bagi Anda yang perlu mengarahkan ulang sebelum sepenuhnya menginisialisasi router menggunakan React Routeratau React Router DomAnda dapat memberikan redirect dengan hanya mengakses objek sejarah dan mendorong negara baru ke dalamnya dalam konstruk Anda app.js. Pertimbangkan yang berikut ini:

function getSubdomain(hostname) {
    let regexParse = new RegExp('[a-z\-0-9]{2,63}\.[a-z\.]{2,5}$');
    let urlParts = regexParse.exec(hostname);
    return hostname.replace(urlParts[0], '').slice(0, -1);
}

class App extends Component {

    constructor(props) {
        super(props);


        this.state = {
            hostState: true
        };

        if (getSubdomain(window.location.hostname).length > 0) {
            this.state.hostState = false;
            window.history.pushState('', '', './login');
        } else {
            console.log(getSubdomain(window.location.hostname));
        }

    }


    render() {
        return (

            <BrowserRouter>
                {this.state.hostState ? (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                        <Route path="/" component={PublicContainer}/>
                    </div>
                ) : (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                    </div>
                )

                }
            </BrowserRouter>)
    }


}

Di sini kami ingin mengubah Rute keluaran bergantung pada subdomain, dengan berinteraksi dengan objek riwayat sebelum komponen merender, kami dapat mengarahkan secara efektif sambil tetap meninggalkan rute kami dengan bijaksana.

window.history.pushState('', '', './login');
li x
sumber