Tepki yönlendiricisini kullanarak programlı olarak gezinin


1429

İle react-routerkullanabilirsinizLink öğeyi, tepki yönlendiricisi tarafından yerel olarak işlenen bağlantılar oluşturmak için .

Dahili olarak görüyorum this.context.transitionTo(...).

Bir navigasyon yapmak istiyorum. Bir bağlantıdan değil, bir açılır listeden (örnek olarak). Bunu kodda nasıl yapabilirim? Nedir this.context?

NavigationKarışımı gördüm , ama bunu olmadan yapabilir miyim mixins?


26
@SergioTapia, bu sorunun büyük bir tepki yönlendirici sürümü, büyük bir React sürümü ve büyük bir javascript sürümü olduğunu hatırlatıyor
George Mauer

5
Reaksiyon yönlendirici v4'ün
chitzui

4
Bu yanıtı kontrol edebilirsiniz stackoverflow.com/questions/44127739/…
Shubham Khatri

4
Bunu cevapladığına sevindim, ama bu kadar karmaşık olması gerektiğine üzgünüm. Bir web uygulamasında gezinmek kolay ve iyi belgelenmiş olmalıdır. VueJS bunu önemsiz kılar. Her bileşen, yönlendirici örneğini otomatik olarak enjekte eder. Dokümanlarında açıkça tanımlanmış bir bölüm var. router.vuejs.org/guide/essentials/navigation.html React'ı birçok şey için seviyorum, ancak bazen çok karmaşık. </rant>
colefner

7
@GeorgeMauer Haklısın. Bu topluluğun konusu bu değil. Bu, çerçeveleri cevaplamak değil, soruları cevaplamakla ilgilidir. Hatırlatma için teşekkürler.
colefner

Yanıtlar:


1431

Kancalı React Router v5.1.0

useHistoryReact> 16.8.0 ve fonksiyonel bileşenleri kullanıyorsanız React Router> 5.1.0'da yeni bir kanca vardır.

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

React Router v4

React Router'ın v4'üyle, bileşenler içindeki programlı yönlendirmeye alabileceğiniz üç yaklaşım vardır.

  1. withRouterÜst düzey bileşeni kullanın .
  2. Kompozisyon kullanın ve bir <Route>
  3. Kullanın context.

React Router çoğunlukla historykütüphane etrafındaki bir pakettir . tarayıcı ve karma geçmişleriyle tarayıcının sizin için historyetkileşimini yönetir window.history. Ayrıca, global bir geçmişi olmayan ortamlar için yararlı bir bellek geçmişi sağlar. Bu özellikle mobil uygulama geliştirme ( react-native) ve Düğüm ile birim testi için kullanışlıdır .

Bir historyörneğin gezinmek için iki yöntemi vardır: pushve replace. Eğer historyziyaret edilen konumlar dizisi olarak düşünüyorsanız, diziye pushyeni bir konum ekler ve dizideki replacegeçerli konumu yenisiyle değiştirir. Genellikle push, gezinirken yöntemi kullanmak isteyeceksiniz .

Yönlendirici Tepki önceki sürümlerinde, kendi yaratmak zorunda historyörneği, ancak v4 içinde <BrowserRouter>, <HashRouter>ve <MemoryRouter>sizin için tarayıcı, karma ve bellek örneklerini oluşturur bileşenler. React Router, historyyönlendiricinizle ilişkilendirilmiş örneğin özelliklerini ve yöntemlerini ,router nesnenin .

1. kullanın withRouter Üst düzey bileşeni

Üst withRouterdüzey bileşen historynesneyi bileşenin bir pervanesi olarak enjekte eder . Bu, ile uğraşmak zorunda kalmadan pushve replaceyöntemlerine erişmenizi sağlar 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. Kompozisyon kullanın ve bir <Route>

<Route>Bileşen sadece eşleşen konumları için değil. Yolsuz bir rota oluşturabilirsiniz ve bu yol daima geçerli konumla eşleşir . <Route>Bileşeni aynı sahne geçer withRoutererişmek mümkün olacak, böylece historyaracılığıyla yöntemleri historypervane.

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

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

3. Bağlamı kullanın *

Ama muhtemelen yapmamalısın

Son seçenek, yalnızca React'in bağlam modeliyle rahatça çalışabilmeniz durumunda kullanmanız gereken seçenektir (React'ın Bağlam API'si v16 itibariyle stabildir).

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 ve 2 uygulamak için en basit seçimlerdir, bu nedenle çoğu kullanım durumunda en iyi bahislerinizdir.


24
Yöntem 1 bu şekilde withRouter (({history}) => {console.log ("hhhhhhhh"); history.push ('/ bets')}); Ama yönlendirici 4 ile hiç çalışmadı
Dmitry Malugin

57
NE!? Tüm bileşenlerimin withRouteraltından geçmek yerine kullanabilir miyim history?? Gahh Dokümanları okumak için daha fazla zaman harcamak lazım ...
hellojeffhall

18
history.push('/new-location')Bu davranışı bir Button veya başka bir DOM öğesine eklemeden nasıl çalıştırabilirsiniz ?
Neil

4
olarak hata atmaUnexpected use of 'history' no-restricted-globals
Pardeep Jain

18
contextreaksiyon 16'dan itibaren artık deneysel değil
trysis

920

React-Router 5.1.0+ Yanıt (kancalar ve Reaksiyon> 16.8 kullanarak)

useHistoryFonksiyonel Bileşenler üzerindeki yeni kancayı kullanabilir ve Programlı olarak gezinebilirsiniz:

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

function HomeButton() {
  let history = useHistory();
  // use history.push('/some/path') here
};

React-Router 4.0.0+ Yanıt

4.0 ve üzeri sürümlerde, geçmişi bileşeninizin bir pervanesi olarak kullanın.

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

NOT: this.props.history, bileşeninizin oluşturulmadığı durumda mevcut değildir <Route>. <Route path="..." component={YourComponent}/>Bileşeninizde this.props.history olması için şunu kullanmalısınız:

React-Router 3.0.0+ Yanıt

3.0 ve üzeri sürümlerde, yönlendiriciyi bileşeninizin desteği olarak kullanın.

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

React-Router 2.4.0 ve üzeri Yanıt

2.4 ve üzeri sürümlerde, yönlendiriciyi bileşeninizin bir pervanesi olarak almak için daha yüksek bir sipariş bileşeni kullanın.

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 ve üzeri Yanıt

Bu sürüm 1.x ile geriye dönük olarak uyumludur, bu nedenle Yükseltme Kılavuzu'na gerek yoktur. Sadece örnekleri incelemek yeterince iyi olmalı.

Bununla birlikte, yeni desene geçmek isterseniz, yönlendiricinin içinde erişebileceğiniz bir tarayıcıHarika modülü vardır.

import { browserHistory } from 'react-router'

Artık tarayıcı geçmişinize erişebiliyorsunuz, böylece itme, değiştirme vb.

browserHistory.push('/some/path')

Daha fazla okuma: Tarihler ve Navigasyon


React-Router 1.xx Yanıt

Ayrıntıları yükseltmeyeceğim. Bu konuda okuyabilirsiniz konuyu Yükseltme Kılavuzu'nda

Buradaki soru ile ilgili ana değişiklik, Navigasyon mixinden Geçmişe geçiştir. Şimdi rotayı değiştirmek için tarayıcı geçmişiniAPI kullanıyor,pushState() .

İşte Mixin kullanan bir örnek:

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

Bunun Historygeldiğini unutmayın raf / tarih projesinden . React-Router'ın kendisinden değil.

Herhangi bir nedenden dolayı (belki de ES6 sınıfı nedeniyle) Mixin'i kullanmak istemiyorsanız, yönlendiriciden aldığınız geçmişe erişebilirsiniz. this.props.history . Yalnızca Yönlendiriciniz tarafından oluşturulan bileşenler için erişilebilir olacaktır. Bu nedenle, herhangi bir alt bileşende kullanmak istiyorsanız, bir özellik olarak geçirilmesi gerekir props.

Yeni sürüm hakkında daha fazla bilgiyi şu adreste bulabilirsiniz: 1.0.x belgelerinde

Burada özellikle bileşeninizin dışına gitmeyle ilgili bir yardım sayfası

Bir referans almanızı history = createHistory()ve bunu çağırmanızı önerir replaceState.

React-Router 0.13.x Yanıt

Aynı sorunu yaşadım ve sadece tepki yönlendiriciyle birlikte gelen Navigasyon mixin ile çözüm bulabildim.

İşte böyle yaptım

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

Erişmeye transitionTo()gerek kalmadan arayabiliyordum.context

Veya süslü ES6'yı deneyebilirsiniz 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
};

Tepki-Yönlendirici-Redux

Not: Redux kullanıyorsanız, React-Redux ile aynı yaklaşımı kullanarak ReactRouter için redux bağları veren React-Router-Redux adlı başka bir proje daha var

React-Router-Redux, eylem oluşturucuların içinden kolayca gezinmenizi sağlayan birkaç yöntem sunar. Bunlar, React Native'de mevcut mimariye sahip insanlar için özellikle yararlı olabilir ve React Web'de aynı kalıpları minimum kaynama ek yükü ile kullanmak isterler.

Aşağıdaki yöntemleri keşfedin:

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

Redux-Thunk ile örnek bir kullanım :

./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>

3
Ben kullanıyorum v2.4.0ama belirtilen yaklaşım benim için çalışmıyor, benim app hiç render ve konsol çıktıları: Uncaught TypeError: (0 , _reactRouter.withRouter) is not a functionİşte benim SO post bağlantısı: stackoverflow.com/questions/37306166/…
nburk

7
Bu kabul edilen cevap olmalı, kabul edilen cevap biraz karışıklık ve çok eski. @GiantElk Ben sürüm için cevap açıklandığı gibi çalışmasını var 2.6.0.
JMac

2
Bu yaklaşım hala sürüm için önerilen yöntem 3.0.xmi? Birçok insan contextyolu kullanıyor gibi görünüyor .
velop

6
4.0'da bu.props.history mevcut değil. Ne oluyor?
Nicolas S.Xu

4
@ NicolasS.Xu this.props.history, bileşeninizin oluşturulmadığı durumda mevcut değildir <Route>. Sen kullanmalıdır <Route path="..." component={YourComponent}/>olması this.props.historyhalinde YourComponent.
vogdb

508

React-Router v2

En son sürüm ( v2.0.0-rc5) için, önerilen gezinme yöntemi doğrudan geçmiş singletonuna itmektir. Bunu, Bileşenler dışında gezinme belgesinde çalışırken görebilirsiniz .

İlgili alıntı:

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

Yeni API-yönlendirici tepki kullanıyorsanız, faydalanmak gerekir historydan this.propsne zaman bileşenlerin kadar içi:

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

Ayrıca sunar, pushStateancak bu, kaydedilen her uyarı için kullanımdan kaldırılır.

Kullanıyorsanız react-router-redux, aşağıdaki pushgibi gönderebileceğiniz bir işlev sunar :

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

Ancak bu, gerçekte sayfaya gitmek için değil, yalnızca URL'yi değiştirmek için kullanılabilir.


15
Daha yeni API'nın kullanmadığını, import { browserHistory } from './react-router'ancak bunun yerine geçmiş oluşturduğunu unutmayın import createBrowserHistory from 'history/lib/createBrowserHistory'. Daha sonra history, bileşenlerden erişebilirsiniz :this.props.history('/some/path')
Ricardo Pedroni

7
var browserHistory = require('react-router').browserHistory; browserHistory.goBack();
Bobby

7
tepki-yönlendirici-redux pushsadece URL'yi değiştirir, aslında sayfayı değiştirmez. , İthalat yapmak için hem browserHistorygelen react-routerve kullanımı browserHistory.push('/my-cool-path'). Ne yazık ki, bu bulmak süper kolay değil. github.com/reactjs/react-router/blob/master/docs/guides/…
Andrew Samuelsen

4
This.props.history.push ('/') kullanıyorum ama sadece URL değişiyor ... Burada gerçek bir yönlendirme yok. Neyi kaçırıyorum?
rgcalsaverini

2
Ben sadece son react-routerv4
spik3s

56

Burada ile bunu nasıl react-router v2.0.0sahip ES6 . react-routerkarışımlardan uzaklaştı.

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
}

5
Şu anki önerinin history@Bobby tarafından belirtilen singletonu kullanmak olduğuna inanıyorum . Sen olabilir kullanmak context.routerancak başlatmasını olarak birim test gerçekten zor bu bileşenleri yapıyoruz sadece komponent bağlamında bu olmayacağını.
George Mauer

2
@GeorgeMauer Kodun çalıştığı yere bağlı olduğunu düşünüyorum. Tepki belgelerine göre, sunucuda çalıştırılıyorsa context.router kullanımı önerilir. github.com/reactjs/react-router/blob/master/upgrade-guides/…
KumarM

50

React-Router 4.x Cevap:

Sonunda, dış bileşenleri bile taşıyabildiğim tek bir tarih nesnesine sahip olmayı seviyorum. Yapmak istediğim, istek üzerine içe aktardığım tek bir history.js dosyasına sahip olmak ve sadece onu işlemek.

Sadece değişikliğine sahip BrowserRouterRouter'e ve tarih pervane belirtin. Bu, sizin için hiçbir şey değiştirmez, ancak istediğiniz gibi işleyebileceğiniz kendi geçmiş nesneniz olması.

Tarafından kullanılan kütüphane geçmişini yüklemeniz gerekir react-router.

Örnek kullanım, ES6 gösterimi:

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

16 Nisan 2018'i DÜZENLE:

Bir bileşenden gerçekte oluşturulmuş bir bileşenden gezinmeniz gerekiyorsa Route, sahne kısmından geçmişe aşağıdaki gibi de erişebilirsiniz:

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

2
React Router dokümanları bize, çoğu durumda Routerbunun yerine kullanmanız gerekmediğini söyler BrowserRouter. nesneyi sizin için BrowserRouteroluşturur ve korur history. Kendinizinkini oluşturmak için varsayılan olmamalısınız, ancak ["Redux gibi durum yönetimi araçlarıyla derin entegrasyona ihtiyacınız varsa."] Reakttraining.com/react-router/web/api/Router
bobbyz

2
Bu zaman ve deneyim boyunca öğrendiğim bir şey. Varsayılanı kullanmak genellikle iyi bir uygulama olsa da, this.props.historyhenüz bir bileşen veya bir React bileşeni olarak inşa edilmemiş herhangi bir araç olmayan bir sınıfta böyle bir şey yapmama yardımcı olabilecek bir çözüm bulamadım. sahne geçebilir. Geri bildiriminiz için teşekkürler :)
Eric Martin

44

Bunun için, sunucu tarafını kontrol etmeyen ve bu nedenle karma yönlendirici v2 kullanıyor:

Senin yerleştirin geçmişini (örneğin app_history.js ES6) ayrı bir dosya içine:

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

export default appHistory;

Ve her yerde kullanın!

Reat-router için giriş noktanız (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"]'));

Herhangi bir bileşenin içindeki gezinmeniz (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()
  }
})

1
Teşekkürler. Belki bir şey eksik. Bu ilk iki cevapla aynı değil mi?
George Mauer

2
"Karma" gezinme kullanırken, "tepki yönlendirici" v2'de ek modül "geçmişi" yüklemeniz gerekir (garip karma sorgularından kaçınmak istiyorsanız) ve browserHistory kullanmak yerine useRouterHistory (createHashHistory) ( {queryKey: false}). Bunu yayınlamamın ana nedeni budur. Karma geçmişiyle nasıl gezileceğini gösterdim.
Alexey Volodko

1
Oh, anlıyorum, haklısın. Artık bu projede değilim ama bence tercih edilen yol her historyiki yaklaşım için de kullanmak
George Mauer

4
neden bu cevap en iyisi değil? Neden Bağlam veya HOC veya olay prototipleri ile ilgili tüm sorunlara giriyoruz, neden sadece geçmişi içe aktarmıyor ve istediğimiz herhangi bir yerde kullanmıyorsunuz? sadece takas anlamaya çalışıyor
storm_buster

@storm_buster, ödünleşim yok. ES6 modüllerimiz var ve bunları kullanmalıyız! Bu, her şey için aracınızı (bu durumda tepki verir) kullanmanın tipik bir vitrinidir, hatta gerçekten kullanmak istemediğiniz şeyler için bile.
Capaj

40

Reaksiyon Router V4

tl: dr;

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

Basit ve bildirime cevap kullanmak gerektiğidir <Redirect to={URL} push={boolean} />birliktesetState()

push: boolean - true olduğunda, yeniden yönlendirme geçerli girişi değiştirmek yerine tarihe yeni bir giriş gönderir.


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

Tam örnek burada . Daha fazlasını buradan okuyun .

PS. Örnek, durumu başlatmak için ES7 + Özellik Başlatıcıları kullanır . İlgileniyorsanız buraya da bakın .


Bu bulduğum en iyi cevap. Yeniden withRouteryüklenen rotadayken kullanmak işe yaramadı. Bizim durumumuzda, biz seçici ya yapmak zorunda setState(neden return <Redirect>rotada ya da zaten varsa) history.push()başka bir yerden.
karmakaze

Çok, çok zeki. Ve yine de çok basit. Tks. Tüm satırdaki tıklamayı işlemek istediğim için ReactRouterTable içinde kullandım. Durumu ayarlamak için onRowClick üzerinde kullanılır. setState ({navigateTo: "/ path /" + row.uuid});
Lovato

bu kurşun geçirmez bir cevap.
Nitin Jadhav

31

Uyarı: Bu yanıt 1.0'dan önceki yalnızca ReactRouter sürümlerini kapsar

Bu cevabı daha sonra 1.0.0-rc1 kullanım durumlarıyla güncelleyeceğim!

Bunu mixins olmadan da yapabilirsiniz.

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

Bağlamlı gotcha contextTypes, sınıfta tanımlayana kadar erişilemez olmasıdır .

Bağlamın ne olduğuna gelince, sahne eşyası gibi, ebeveynden çocuğa aktarılan bir nesnedir, ancak her seferinde sahne tekrarlarını bildirmek zorunda kalmadan örtük olarak aktarılır. Bkz. Https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html


26

Bir şey yolunda gitmeden önce bunu yapmanın en az 10 yolunu denedim!

@Felipe Skinner'ın withRouteryanıtı benim için biraz zorlayıcıydı ve yeni "ExportedWithRouter" sınıf adları yapmak istediğimden emin değildim.

Şu anki React-Router 3.0.0 ve ES6 etrafında bunu yapmanın en basit ve en temiz yolu:

ES6 ile React-Router 3.xx:

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

veya varsayılan sınıfınız değilse aşağıdaki gibi dışa aktarın:

withRouter(Example);
export { Example };

3.xx'de, <Link>bileşenin kendisinin kullandığına dikkat edin router.push, böylece <Link to=etiketi geçireceğiniz her şeyi aktarabilirsiniz , örneğin:

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

1
Tamamen iyi çalışıyor. Ancak kod 200 OKyerine yanıt verir 30x. Bu sorunu nasıl düzeltebilirim?
Muhammad Ateeq Azam

1
Emin değil. Bu benim için hiç gelmedi çünkü bu harici bir istek değil - sayfadaki içeriği değiştirmek için sadece sayfanın kendi kodunu kullanan tarayıcınız. İsterseniz her zaman manuel bir javascript yönlendirmesi yapabilirsiniz.
Ben Wheeler

1
Ayrıca bir sınıf dekoratörü olarak @withRouter ile de kullanılabilir ... mobx ile harika gidiyor
Dan

21

Navigasyonu programlı olarak yapmak için, props.history'deki yeni bir geçmişi itmeniz gerekir component, böylece böyle bir şey sizin için işi yapabilir:

//using ES6
import React from 'react';

class App extends React.Component {

  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick(e) {
    e.preventDefault()
    /* Look at here, you can add it here */
    this.props.history.push('/redirected');
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          Redirect!!!
        </button>
      </div>
    )
  }
}

export default App;

Lütfen tepki yönlendirici sürümünü yazın
Ash

19

ES6 + React bileşenleri için aşağıdaki çözüm benim için çalıştı.

Felippe skinner'ı takip ettim, ama benim gibi yeni başlayanlara yardımcı olmak için uçtan uca bir çözüm ekledim.

Kullandığım sürümler aşağıdadır:

"tepki yönlendirici": "^ 2.7.0"

"tepki": "^ 15.3.1"

Reat-router kullanarak programlı navigasyon kullandığım tepki bileşenim aşağıdadır:

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;

Yönlendiricimin yapılandırması aşağıdadır:

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

19

En iyi yaklaşım olmayabilir ama ... Reat-router v4 kullanarak, aşağıdaki Typcript bazıları için bir fikir verebilir.

Aşağıdaki oluşturulmuş bileşende, örneğin LoginPage, routernesneye erişilebilir ve sadece router.transitionTo('/homepage')gezinmek için arayın .

Navigasyon kodu alındı dan .

"react-router": "^4.0.0-2", "react": "^15.3.1",

import Router from 'react-router/BrowserRouter';
import { History } from 'react-history/BrowserHistory';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();

interface MatchWithPropsInterface {
  component: typeof React.Component,
  router: Router,
  history: History,
  exactly?: any,
  pattern: string
}

class MatchWithProps extends React.Component<MatchWithPropsInterface,any> {
  render() {
    return(
      <Match {...this.props} render={(matchProps) => (
             React.createElement(this.props.component, this.props)

        )}
       />
    )
  }
}

ReactDOM.render(
    <Router>
      {({ router }) => (
        <div>
          <MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
          <Miss component={NotFoundView} />
        </div>
      )}
    </Router>,

   document.getElementById('app')
);


1
Neden Yönlendirici ve Tarayıcı Geçmişi ile kullanmıyorsunuz?
Erwin Mayer

1
@Erwin API, v4'te farklıdır. Bu github.com/ReactTraining/react-router/issues/3847 adresine bakın .
mcku

1
@mcku reaktif yönlendirici v4 için typescript dts dosyanızı nereden buldunuz?
jmathew

1
@jmathew tepki yönlendirici v4 için herhangi bir tür tanımım yok
mcku

16

In Tepki-Yönlendirici v4 ve ES6

Sen kullanabilirsiniz withRouterve this.props.history.push.

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

class Home extends Component {

    componentDidMount() {
        this.props.history.push('/redirect-to');
    }
}

export default withRouter(Home);

2
Zaten diğer birkaç cevapta da belirtilmiştir (en üstteki cevabın uzunluğu dahil)
George Mauer

13

Kullanmak withRouterSınıf tabanlı bir bileşenle aşağıdaki gibi bir şey deneyin. Kullanılacak dışa aktarma deyimini değiştirmeyi unutmayın withRouter:

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

class YourClass extends React.Component {
  yourFunction = () => {
    doSomeAsyncAction(() =>
      this.props.history.push('/other_location')
    )
  }

  render() {
    return (
      <div>
        <Form onSubmit={ this.yourFunction } />
      </div>
    )
  }
}

export default withRouter(YourClass);

11


José Antonio Postigo ve Ben Wheeler'ın
yeniliğinden önceki cevaba dayanarak ? daktiloda yazılmalı
ve dekoratörün kullanımı
VEYA statik özellik / alan kullanımı

import * as React from "react";
import Component = React.Component;
import { withRouter } from "react-router";

export interface INavigatorProps {
    router?: ReactRouter.History.History;
}

/**
 * Note: goes great with mobx 
 * @inject("something") @withRouter @observer
 */
@withRouter
export class Navigator extends Component<INavigatorProps, {}>{
    navigate: (to: string) => void;
    constructor(props: INavigatorProps) {
        super(props);
        let self = this;
        this.navigate = (to) => self.props.router.push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

/**
 * Non decorated 
 */
export class Navigator2 extends Component<INavigatorProps, {}> {

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

    navigate: (to: string) => void;
    constructor(props: INavigatorProps, context: any) {
        super(props, context);
        let s = this;
        this.navigate = (to) =>
            s.context.router.push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

bugün npm yüklüyse. "tepki yönlendirici": "^ 3.0.0" ve
"@ türler / tepki yönlendirici": "^ 2.0.41"


11

React-Router v4 ufukta, şimdi bunu yapmanın yeni bir yolu var.

import { MemoryRouter, BrowserRouter } from 'react-router';

const navigator = global && global.navigator && global.navigator.userAgent;
const hasWindow = typeof window !== 'undefined';
const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
const Router = isBrowser ? BrowserRouter : MemoryRouter;

<Router location="/page-to-go-to"/>

reat-lego , tepki yönlendiricinin nasıl kullanılacağını / güncelleneceğini gösteren örnek bir uygulamadır ve uygulamada gezinen örnek fonksiyonel testleri içerir.


5
Bu, bir yaşam döngüsü kancası veya redux gibi bir şeyden nasıl gezinileceğini merak etsem de, oluşturma işlevinden gezinmek için harika bir şey mi?
Ruben Martinez Jr.

11

Reaksiyon yönlendiricisinde v4. Programlı olarak ilerlemek için bu iki yolu izliyorum.

1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")

İki numaralı

Geçmiş yığınındaki geçerli girişi değiştirir

Sahne alanında tarih almak için bileşeninizi şununla sarmanız gerekebilir:

withRouter


Teşekkürler!! En İyi Cevap
Taha Farooqui

9

Karma veya tarayıcı geçmişi kullanıyorsanız,

hashHistory.push('/login');
browserHistory.push('/login');

2
hashHistory.push, verir undefined öğesinin "push" özelliği okunamıyor. Bunları nereden alıyorsunuz?
ArchNoob

{tepki yönlendiriciden "{hashHistory} dosyasını içe aktarın; üstte bu şekilde içe aktarabilirsiniz.
Zaman Afzal

Kod örneğinizi redux saga dosyamdan, nasıl söylediğiniz ve kullandığınız gibi içe aktarıyorum ama o TypeError almaya devam ediyorum.
ArchNoob

8

Geçerli React sürümü (15.3) this.props.history.push('/location');ile benim için çalıştı, ancak aşağıdaki uyarıyı gösterdi:

browser.js: 49 Uyarı: [tepki yönlendirici] props.historyve context.historykullanımdan kaldırıldı. Lütfen kullanın context.router.

ve şu şekilde kullanarak çözdüm context.router:

import React from 'react';

class MyComponent extends React.Component {

    constructor(props) {
        super(props);
        this.backPressed = this.backPressed.bind(this);
    }

    backPressed() {
        this.context.router.push('/back-location');
    }

    ...
}

MyComponent.contextTypes = {
    router: React.PropTypes.object.isRequired
};

export default MyComponent;

1
Bu V4 için çalışıyor. Şey ... yakın ... aslında bu.context.router.history.push ('/ back-location') olmalı;
velohomme

7

React-Router V4

sürüm 4 kullanıyorsanız, sadece bir eylem gönderebileceğiniz ve her şeyin işe yaradığı kütüphanemi (Utanmaz fiş) kullanabilirsiniz!

dispatch(navigateTo("/aboutUs"));

Trippler


5

Reat-router v4 üzerinde bunu uygulama konusunda sorun yaşayanlar.

İşte redux eylemlerinden tepki uygulamasında gezinmek için çalışan bir çözüm.

history.js

import createHistory from 'history/createBrowserHistory'

export default createHistory()

App.js / Route.jsx

import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
 <Route path="/test" component={Test}/>
</Router>

another_file.js VEYA redux dosyası

import history from './history' 

history.push('/test') // this should change the url and re-render Test component

Bu yoruma teşekkürler: ReactTraining sorunları yorum


4

RR4 w / redux'u tepki yönlendirici-redux ile eşleştirirseniz , yönlendirme eylemi yaratıcılarını da react-router-reduxkullanmak bir seçenektir.

import { push, replace, ... } from 'react-router-redux'

class WrappedComponent extends React.Component {
  handleRedirect(url, replaceState = true) { 
    replaceState 
      ? this.props.dispatch(replace(url)) 
      : this.props.dispatch(push(url)) 
  }
  render() { ... }
}

export default connect(null)(WrappedComponent)

Eşzamansız akışı yönetmek için redux thunk / saga kullanıyorsanız, yukarıdaki eylem oluşturucuları redux eylemlerine aktarın ve mapDispatchToProps kullanarak bileşenleri reaksiyona sokmak için kanca daha iyi olabilir.


1
react-router-reduxuzun süredir kullanımdan kaldırıldı / arşivlendi
oligofren

4

useHistoryKancayı vatansız bir bileşende de kullanabilirsiniz . Dokümanlardan örnek.

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

  return (
    <button type="button" onClick={() => history.push("/home")}>
      Go home
    </button>
  )
}

Not: Kancalar eklendi react-router@5.1.0ve gereklireact@>=16.8


1
İyi çağrı, hangi tepki yönlendiricinin ve tepkiyi ifade eden sürümüne dikkat eder misiniz? Bu her zaman mevcut olmayan yeni bir değişiklik
George Mauer

3

Yazarken doğru cevap benim içindi

this.context.router.history.push('/');

Ancak bileşeninize PropTypes eklemeniz gerekir

Header.contextTypes = {
  router: PropTypes.object.isRequired
}
export default Header;

PropType'ları içe aktarmayı unutmayın

import PropTypes from 'prop-types';

Lütfen tepki yönlendiricinin sürümünü ve tepki yönlendiriciden ne aldınız
Ash

İçe aktarılacak bir şey yok ve bu "tepki yönlendirici" sürümü: "^ 4.2.0"
webmaster

3

Belki en iyi çözüm değil ama işi hallediyor:

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

// create functional component Post
export default Post = () => (
    <div className="component post">

        <button className="button delete-post" onClick={() => {
            // ... delete post
            // then redirect, without page reload, by triggering a hidden Link
            document.querySelector('.trigger.go-home').click();
        }}>Delete Post</button>

        <Link to="/" className="trigger go-home hidden"></Link>

    </div>
);

Temel olarak, bir eyleme bağlı bir mantık (bu durumda bir gönderi silme) sonunda yönlendirme için bir tetikleyici çağırır. Bu ideal değildir, çünkü işaretlemenize bir DOM düğümü 'tetikleyici' ekleyeceksiniz, böylece gerektiğinde kolayca arayabilirsiniz. Ayrıca, bir React bileşeninde istenmeyebilecek olan DOM ile doğrudan etkileşime gireceksiniz.

Yine de, bu tür bir yönlendirme sıklıkla gerekli değildir. Dolayısıyla, bileşen işaretlemenizdeki bir veya iki ekstra gizli bağlantı, özellikle anlamlı adlar verirseniz, çok fazla zarar vermez.


Bunu neden kabul edilen çözüm üzerinde kullandığınızı açıklayabilir misiniz?
George Mauer

Tartışılan soruna sadece alternatif bir çözümdür. Daha önce de belirtildiği gibi, ideal değil ama programlı yönlendirmeler için iyi çalışıyor.
neatsu

2

Bu benim için çalıştı, özel ithalata gerek yok:

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>

Tabii ki bunun özel ithalata ihtiyacı var - bileşeniniz tek başına historyeklenmedi props. Bu bir Hoc Eğer kullanımda amacıyla ithalat gerekir ki geliyor (bileşenler tarafından doğrudan gönderilen Routeotomatik olarak Hoc ama o zaman için bir ithalat ihtiyacımız tarafından sarılmıştır Route...)
George Mauer

2

bunun yerine hookrouter kullanın, tepki yönlendiriciye modern alternatif

https://www.npmjs.com/package/hookrouter

import { useRoutes, usePath, A} from "hookrouter";

seçme kutusuyla bağlantı kurma hakkında OP sorusunu cevaplamak için bunu yapabilirsiniz:

navigate('/about');

Bilginize. Yazarın kendisi bu kütüphaneye "kavram kanıtı" adını veriyor ve neredeyse bir yıldır (Haziran 2019) hiçbir etkinliği yoktu.
MEMark

@MEMark zaten mükemmel olduğu için
StefanBob

Peki, 38 açık konu, sürüm 2.0'ın yazara göre tam bir yeniden yazma olacağı gerçeğiyle birlikte, aksi diyor.
MEMark

1

React Router v4 + için

İlk oluşturma sırasında gezinmeniz gerekmediğini varsayarsak (bunun için <Redirect> bileşeni ) , bu bizim uygulamamızda yaptığımız şeydir.

Null döndüren boş bir rota tanımlayın, bu geçmiş nesnesine erişmenizi sağlar. Bunu en üst düzeyde yapmanız gerekir.Router , tanımlandığınız .

Şimdi üzerinde yapılabilir her şeyi yapabilirim tarihin gibi history.push(), history.replace(), history.go(-1)vb!

import React from 'react';
import { HashRouter, Route } from 'react-router-dom';

let routeHistory = null;

export function navigateTo(path) {
  if(routeHistory !== null) {
    routeHistory.push(path);
  }
}

export default function App(props) {
  return (
    <HashRouter hashType="noslash">
      <Route
        render={({ history }) => {
          routeHistory = history;
          return null;
        }}
      />
      {/* Rest of the App */}
    </HashRouter>
  );
}

1

tepki yönlendirici-dom: 5.1.2

  • Bu sitede, tümü tarayıcıda dinamik olarak oluşturulan 3 sayfa vardır.

  • Sayfa hiç yenilenmese de, React Router'ın sitede gezinirken URL'yi nasıl güncel tuttuğuna dikkat edin. Bu, tarayıcı geçmişini korur ve geri düğmesi ve yer imleri gibi şeylerin düzgün çalışmasını sağlar

  • Bir Anahtar tüm alt öğelerini inceler ve yolu geçerli URL ile eşleşen ilk öğeyi oluşturur. Birden fazla rotanız olduğunda istediğiniz zaman kullanın, ancak aynı anda yalnızca bir tanesinin oluşturulmasını istiyorsunuz

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";



export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />

        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

// You can think of these components as "pages"
// in your app.

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
    </div>
  );
}```

SO hoş geldiniz! Bir soruyu bu kadar çok cevapla yanıtladığınızda, avantajlarınızı göstermeye çalışın.
David García Bodego

Bu aynı zamanda, biçimlendirme ile değil, zorunlu js'den programlı olarak nasıl yapılacağı sorusuna cevap vermez.
George Mauer

1

Cevabımda programlı olarak bir rotaya yönlendirmenin 3 farklı yolu var. Bazı çözümler halihazırda sunulmuştur, ancak aşağıdakiler yalnızca ek bir demo uygulaması olan fonksiyonel bileşenler için odaklanmıştır .

Aşağıdaki sürümleri kullanarak:

tepki: 16.13.1

tepki: 16.13.1

tepki yönlendirici: 5.2.0

tepki yönlendirici-dom: 5.2.0

daktilo ile yazılmış yazı: 3.7.2

Yapılandırma:

Öncelikle çözüm HashRouteraşağıdaki gibi yapılandırılmış kullanıyor :

<HashRouter>
    // ... buttons for redirect

    <Switch>
      <Route exact path="/(|home)" children={Home} />
      <Route exact path="/usehistory" children={UseHistoryResult} />
      <Route exact path="/withrouter" children={WithRouterResult} />
      <Route exact path="/redirectpush" children={RedirectPushResult} />
      <Route children={Home} />
    </Switch>
</HashRouter>

Gönderen belgeler hakkında <HashRouter>:

Bir <Router>URL'ye (yani karma bölümünü kullanan window.location.hash) URL ile senkronize UI tutmak için.

Çözümler:

  1. Kullanarak <Redirect>itmek için kullanma useState:

İşlevsel bir bileşende ( RedirectPushActiondepomdaki bileşen) kullanarak useStateyeniden yönlendirmeyi işlemek için kullanabiliriz . Zor kısım, yeniden yönlendirme gerçekleştiğinde, redirectdurumu tekrar ayarlamamız gerekir false. Gecikme setTimeOutile kullanarak 0React bitene kadar bekliyoruzRedirect o zaman bir dahaki sefere kullanmak için düğmeye geri almak DOM.

Lütfen aşağıdaki örneğimi bulun:

const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
    let render = null;
    if (redirect) {
        render = <Redirect to="/redirectpush" push={true} />

        // in order wait until commiting to the DOM
        // and get back the button for clicking next time
        setTimeout(() => setRedirect(false), 0);
    }
    return render;
}, [redirect]);

return <>
    {handleRedirect()}
    <button onClick={() => setRedirect(true)}>
        Redirect push
    </button>
</>

Gönderen <Redirect>belgeler:

Bir oluşturma <Redirect>yeni bir konuma gider. Yeni konum, sunucu tarafı yönlendirmelerinin (HTTP 3xx) yaptığı gibi geçmiş yığınındaki geçerli konumu geçersiz kılar.

  1. useHistoryKanca kullanarak :

Benim çözümümde UseHistoryActionaşağıdakileri temsil eden bir bileşen var :

let history = useHistory();

return <button onClick={() => { history.push('/usehistory') }}>
    useHistory redirect
</button>

useHistoryKanca bize bize programlı navigasyon veya değiştirme yolları yardımcı tarih nesnesine erişim sağlar.

  1. Kullanılması withRouter, almak historyden props:

Adlı bir bileşen oluşturuldu WithRouterAction, aşağıdaki gibi görüntülenir:

const WithRouterAction = (props:any) => {
    const { history } = props;

    return <button onClick={() => { history.push('/withrouter') }}>
        withRouter redirect
    </button>
}

export default withRouter(WithRouterAction);

withRouterBelgelerden okuma :

Sen erişebilirsiniz historynesnenin özellikleri ve en yakın <Route>yoluyla 'ın maçı withRouterÜst düzey bileşeni. withRoutergüncellenmiş geçiren edecek match, locationve historybu hale ne zaman sarılmış bileşene sahne.

Demo:

Daha iyi temsil için bu örneklerle bir GitHub deposu oluşturdum, lütfen aşağıda bulabilirsiniz:

https://github.com/norbitrial/react-router-programmatically-redirect-examples

Umarım bu yardımcı olur!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.