นำทางโดยโปรแกรมโดยใช้ react router


1428

ด้วยreact-routerฉันสามารถใช้Linkองค์ประกอบในการสร้างลิงค์ที่จัดการโดยกำเนิดเราเตอร์

ฉันเห็นการโทรthis.context.transitionTo(...)ภายใน

ฉันต้องการนำทาง ไม่ใช่จากลิงก์ แต่มาจากตัวเลือกแบบเลื่อนลง (เป็นตัวอย่าง) ฉันจะทำสิ่งนี้ในรหัสได้อย่างไร คือthis.contextอะไร

ผมเห็นNavigationmixin แต่ฉันสามารถทำเช่นนี้ไม่mixins?


26
@SergioTapia โปรดจำไว้ว่าคำถามนี้คร่อมปฏิกิริยาของเราเตอร์ที่สำคัญรุ่นใหญ่ของ React และรุ่นใหญ่ของจาวาสคริปต์
George Mauer

5
นี่คือลิงค์ไปยังบทช่วยสอนในเอกสารอย่างเป็นทางการของเราเตอร์ปฏิกิริยา v4: reacttraining.com/react-router/web/guides/scroll-restoration
chitzui

4
คุณสามารถตรวจสอบคำตอบนี้stackoverflow.com/questions/44127739/…
Shubham Khatri

4
ฉันดีใจที่คุณได้รับคำตอบนี้ แต่ฉันเสียใจที่ต้องมีความซับซ้อนนี้ การนำทางภายในแอปพลิเคชันเว็บควรเป็นเอกสารที่ง่ายและดี VueJS ทำให้มันน่ารำคาญ แต่ละองค์ประกอบรับอินสแตนซ์เราเตอร์ที่ฉีดโดยอัตโนมัติ มีส่วนที่กำหนดไว้อย่างชัดเจนในเอกสารของพวกเขา router.vuejs.org/guide/essentials/navigation.htmlฉันชอบ React ในหลาย ๆ อย่าง แต่บางครั้งมันก็ซับซ้อนเกินไป </rant>
colefner

7
@GeorgeMauer คุณพูดถูก นั่นไม่ใช่สิ่งที่ชุมชนนี้เป็นเกี่ยวกับ มันเกี่ยวกับการตอบคำถามไม่ใช่การทะเลาะกันเรื่องกรอบ ขอบคุณสำหรับการเตือน
colefner

คำตอบ:


1429

React Router v5.1.0 พร้อม hooks

มีuseHistoryhook ใหม่ใน React Router> 5.1.0 หากคุณใช้ React> 16.8.0 และส่วนประกอบที่ใช้งานได้

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

ทำปฏิกิริยาเราเตอร์ v4

ด้วย v4 ของ React Router มีสามวิธีที่คุณสามารถใช้เพื่อกำหนดเส้นทางแบบเป็นโปรแกรมภายในส่วนประกอบได้

  1. ใช้withRouterส่วนประกอบลำดับสูงกว่า
  2. ใช้องค์ประกอบและแสดงผล <Route>
  3. contextใช้

React Router ส่วนใหญ่เป็นกระดาษห่อหุ้มรอบ ๆhistoryห้องสมุด historyจัดการกับการโต้ตอบกับเบราว์เซอร์window.historyสำหรับคุณด้วยเบราว์เซอร์และประวัติแฮช นอกจากนี้ยังมีประวัติหน่วยความจำซึ่งมีประโยชน์สำหรับสภาพแวดล้อมที่ไม่มีประวัติทั่วโลก สิ่งนี้มีประโยชน์อย่างยิ่งในการพัฒนาแอพมือถือ ( react-native) และการทดสอบหน่วยด้วย Node

historyเช่นมีสองวิธีการสำหรับการนำ: และpush replaceหากคุณคิดว่าhistoryเป็นอาร์เรย์ของสถานที่ที่เยี่ยมชมpushจะเพิ่มสถานที่ใหม่ให้กับอาร์เรย์และreplaceจะแทนที่ตำแหน่งปัจจุบันในอาร์เรย์ด้วยสถานที่ใหม่ โดยทั่วไปแล้วคุณจะต้องการใช้pushวิธีนี้เมื่อคุณนำทาง

ในเวอร์ชันก่อนหน้าของการตอบสนองเตอร์คุณต้องสร้างของคุณเองhistoryเช่น แต่ใน v4 <BrowserRouter>, <HashRouter>และ<MemoryRouter>ส่วนประกอบจะสร้างเบราว์เซอร์, กัญชาและอินสแตนซ์หน่วยความจำสำหรับคุณ React Router ทำให้คุณสมบัติและวิธีการของhistoryอินสแตนซ์ที่เกี่ยวข้องกับเราเตอร์ของคุณพร้อมใช้งานผ่านบริบทภายใต้routerวัตถุ

1. ใช้withRouterส่วนประกอบลำดับสูงกว่า

withRouterส่วนประกอบลำดับที่สูงกว่าจะฉีดhistoryวัตถุเป็นเสาขององค์ประกอบที่ นี้จะช่วยให้คุณสามารถเข้าถึงpushและวิธีการได้โดยไม่ต้องจัดการกับreplacecontext

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. ใช้องค์ประกอบและแสดงผล <Route>

<Route>องค์ประกอบไม่ได้เป็นเพียงสถานที่ที่ตรงกัน คุณสามารถเรนเดอร์เส้นทางที่ไม่มีเส้นทางได้และมันจะตรงกับตำแหน่งปัจจุบันเสมอ <Route>องค์ประกอบผ่านอุปกรณ์ประกอบฉากเดียวกับwithRouterคุณจึงจะสามารถเข้าถึงhistoryวิธีการผ่านhistoryเสา

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

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

3. ใช้บริบท *

แต่คุณอาจไม่ควร

ตัวเลือกสุดท้ายคือสิ่งที่คุณควรใช้ก็ต่อเมื่อคุณรู้สึกสบายใจที่จะทำงานกับแบบจำลองบริบทของ React (Context API ของ React นั้นมีความเสถียรเหมือน v16)

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 และ 2 เป็นตัวเลือกที่ง่ายที่สุดในการติดตั้งดังนั้นสำหรับกรณีการใช้งานส่วนใหญ่มันเป็นทางออกที่ดีที่สุดของคุณ


24
ฉันพยายามใช้วิธีที่ 1 ด้วยวิธีนี้ withRouter (({history}) => {console.log ("hhhhhhhhh"); history.push ('/ เดิมพัน')}); แต่มันไม่เคยทำงานกับเราเตอร์ 4
Dmitry Malugin

57
อะไร!? ฉันสามารถใช้withRouterแทนการส่งhistoryผ่านส่วนประกอบทั้งหมดได้หรือไม่? Gahh ฉันต้องใช้เวลาอ่านเอกสารมากขึ้น ...
hellojeffhall

18
คุณจะรันhistory.push('/new-location')โดยไม่แนบพฤติกรรมนั้นกับปุ่มหรือองค์ประกอบ DOM อื่น ๆ ได้อย่างไร
Neil

4
เกิดข้อผิดพลาดในการโยนUnexpected use of 'history' no-restricted-globals
Pardeep Jain

18
contextไม่ได้ทำการทดลองอีกต่อไปตั้งแต่วันที่ 16 ตอบสนอง
ลอง

920

React-Router 5.1.0+คำตอบ (ใช้ hooks และ React> 16.8)

คุณสามารถใช้useHistoryเบ็ดใหม่บนส่วนประกอบการทำงานและการนำทางโดยทางโปรแกรม:

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

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

React-Router 4.0.0+คำตอบ

ใน 4.0 ขึ้นไปให้ใช้ประวัติเป็นเสาของส่วนประกอบของคุณ

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

หมายเหตุ: this.props.history <Route>ไม่ได้อยู่ในกรณีที่ส่วนประกอบของคุณไม่ได้แสดงโดย คุณควรใช้<Route path="..." component={YourComponent}/>เพื่อรับ this.props.history ใน YourComponent

React-Router 3.0.0+คำตอบ

ใน 3.0 ขึ้นไปให้ใช้เราเตอร์เป็นอุปกรณ์ของคุณ

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

React-Router 2.4.0+คำตอบ

ใน 2.4 และสูงกว่าให้ใช้ส่วนประกอบลำดับที่สูงขึ้นเพื่อให้เราเตอร์เป็นเสาของส่วนประกอบของคุณ

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+คำตอบ

รุ่นนี้สามารถใช้งานร่วมกับ 1.x ได้ไม่จำเป็นต้องมีคำแนะนำในการอัพเกรด แค่ผ่านตัวอย่างควรจะดีพอ

ที่กล่าวว่าหากคุณต้องการเปลี่ยนเป็นรูปแบบใหม่มีเบราว์เซอร์โมดูลประวัติภายในเราเตอร์ที่คุณสามารถเข้าถึงได้

import { browserHistory } from 'react-router'

ตอนนี้คุณสามารถเข้าถึงประวัติเบราว์เซอร์ของคุณเพื่อให้คุณสามารถทำสิ่งต่างๆเช่นพุช, แทนที่, ฯลฯ ... กดไลค์:

browserHistory.push('/some/path')

อ่านเพิ่มเติม: ประวัติศาสตร์และ การนำทาง


React-Router 1.xxคำตอบ

ฉันจะไม่เข้าไปดูรายละเอียดการอัพเกรด คุณสามารถอ่านเกี่ยวกับเรื่องนั้นได้ในคำแนะนำในการอัพเกรด

การเปลี่ยนแปลงหลักเกี่ยวกับคำถามที่นี่คือการเปลี่ยนแปลงจาก Navigation mixin เป็น History ตอนนี้มันกำลังใช้ประวัติเบราว์เซอร์ API เพื่อเปลี่ยนเส้นทางดังนั้นเราจะใช้ต่อpushState()จากนี้ไป

นี่เป็นตัวอย่างการใช้ Mixin:

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

โปรดทราบว่าสิ่งนี้Historyมาจากโครงการแร็ค / ประวัติ ไม่ได้มาจาก React-Router

หากคุณไม่ต้องการที่จะใช้ Mixin ด้วยเหตุผลบางอย่าง (อาจจะเพราะของชั้น ES6) this.props.historyแล้วคุณสามารถเข้าถึงประวัติศาสตร์ที่คุณได้รับจากเราเตอร์จาก มันจะเข้าถึงได้เฉพาะสำหรับส่วนประกอบที่เราเตอร์ของคุณแสดงผล ดังนั้นถ้าคุณต้องการที่จะใช้ในส่วนเด็ก ๆ propsจะต้องมีการส่งผ่านลงมาเป็นแอตทริบิวต์ผ่าน

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับรีลีสใหม่ได้ที่เอกสารคู่มือ1.0.x

นี่คือหน้าความช่วยเหลือเกี่ยวกับการนำทางนอกส่วนประกอบของคุณโดยเฉพาะ

มันแนะนำให้คว้าการอ้างอิงhistory = createHistory()และเรียกreplaceStateสิ่งนั้น

React-Router 0.13.xคำตอบ

ฉันเจอปัญหาเดียวกันและหาวิธีแก้ปัญหาด้วย Navigation mixin ที่มาพร้อมกับ react-router

นี่เป็นวิธีที่ฉันทำ

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

ฉันสามารถโทรได้transitionTo()โดยไม่จำเป็นต้องเข้าถึง.context

หรือคุณอาจลองใช้ ES6 แฟนซี 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
};

ตอบสนอง-Router-Redux

หมายเหตุ:หากคุณกำลังใช้ Redux มีอีกโครงการที่เรียกว่า React-Router-Reduxที่ให้การเชื่อม Redux สำหรับ ReactRouter โดยใช้วิธีการเดียวกับที่ React-Reduxทำ

React-Router-Redux มีวิธีการไม่กี่วิธีที่ช่วยให้การนำทางอย่างง่ายจากผู้สร้างแอ็คชั่นภายใน สิ่งเหล่านี้มีประโยชน์อย่างยิ่งสำหรับผู้ที่มีสถาปัตยกรรมที่มีอยู่ใน React Native และพวกเขาต้องการใช้รูปแบบเดียวกันใน React Web ด้วยค่าใช้จ่ายที่น้อยที่สุด

สำรวจวิธีการต่อไปนี้:

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

นี่คือตัวอย่างการใช้งานด้วย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>

3
ฉันใช้v2.4.0แต่วิธีดังกล่าวใช้ไม่ได้สำหรับฉันแอปของฉันไม่สามารถแสดงผลได้เลยและคอนโซลเอาต์พุต: Uncaught TypeError: (0 , _reactRouter.withRouter) is not a functionนี่คือลิงก์ไปยังโพสต์ SO ของฉัน: stackoverflow.com/questions/37306166/…
nburk

7
นี่ควรเป็นคำตอบที่ได้รับการยอมรับคำตอบที่ได้รับนั้นค่อนข้างเก่าและเก่ามาก @GiantElk 2.6.0ฉันมีมันทำงานตามที่อธิบายไว้ในคำตอบสำหรับรุ่น
JMac

2
วิธีนี้ยังคงเป็นวิธีที่แนะนำสำหรับรุ่น3.0.xหรือไม่ หลายคนดูเหมือนจะใช้contextวิธีนี้
velop

6
ใน 4.0 this.props.history ไม่มีอยู่ เกิดอะไรขึ้น?
Nicolas S.Xu

4
@ NicolasS.Xu ไม่ได้อยู่ในกรณีที่ส่วนประกอบของคุณไม่ได้แสดงโดยthis.props.history <Route>คุณควรใช้<Route path="..." component={YourComponent}/>ที่จะมีในthis.props.history YourComponent
vogdb

508

React-Router v2

สำหรับรีลีสล่าสุด ( v2.0.0-rc5) วิธีการนำทางที่แนะนำคือกดไปยังซิงเกิลประวัติโดยตรง คุณจะเห็นว่าในการดำเนินการในการนำทางด้านนอกของเอกสารประกอบ

ข้อความที่ตัดตอนมาที่เกี่ยวข้อง:

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

หากใช้ react-router API ที่ใหม่กว่าคุณต้องใช้ประโยชน์historyจากthis.propsเมื่ออยู่ภายในส่วนประกอบดังนั้น:

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

นอกจากนี้ยังมีpushStateแต่ที่ไม่สนับสนุนต่อคำเตือนที่บันทึกไว้

หากใช้react-router-reduxมันมีpushฟังก์ชั่นที่คุณสามารถส่งได้เช่น:

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

อย่างไรก็ตามสิ่งนี้อาจใช้เพื่อเปลี่ยน URL ไม่ใช่เพื่อไปยังหน้าจริง ๆ


15
อย่าลืมว่า API ที่ใหม่กว่านั้นไม่ได้ใช้import { browserHistory } from './react-router'แต่สร้างประวัติโดยใช้import createBrowserHistory from 'history/lib/createBrowserHistory'แทน หลังจากนั้นคุณสามารถเข้าถึงได้historyจากอุปกรณ์ประกอบฉาก:this.props.history('/some/path')
Ricardo Pedroni

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

7
react-router-redux pushจะเปลี่ยน URL เท่านั้นไม่ได้เปลี่ยนหน้าเว็บ จะทำทั้งสองนำเข้าbrowserHistoryจากและการใช้งานreact-router browserHistory.push('/my-cool-path')น่าเสียดายที่นี่ไม่ใช่เรื่องง่ายที่จะหา github.com/reactjs/react-router/blob/master/docs/guides/…
Andrew Samuelsen

4
ฉันใช้ this.props.history.push ('/') แต่มีการเปลี่ยนแปลง URL เท่านั้น ... ไม่มีการกำหนดเส้นทางที่แท้จริงเกิดขึ้นที่นี่ ฉันพลาดอะไรไป
rgcalsaverini


56

นี่คือวิธีที่คุณทำเช่นนี้กับreact-router v2.0.0กับES6 react-routerได้ย้ายออกจาก 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
}

5
ฉันเชื่อว่าคำแนะนำปัจจุบันคือการใช้historyซิงเกิลตันตามที่ระบุโดย @Bobby คุณสามารถใช้context.routerแต่คุณกำลังทำให้มันยากมากที่จะทดสอบหน่วยองค์ประกอบเหล่านั้นเนื่องจากการสร้างอินสแตนซ์เพียงแค่องค์ประกอบนั้นจะไม่ได้รับสิ่งนี้ในบริบท
George Mauer

2
@ GeorgeMauer ฉันคิดว่ามันขึ้นอยู่กับที่รหัสทำงานอยู่ ตามเอกสารตอบสนองการใช้ context.router แนะนำให้ใช้ถ้ามันทำงานบนเซิร์ฟเวอร์ github.com/reactjs/react-router/blob/master/upgrade-guides/…
KumarM

50

React-Router 4.x คำตอบ:

ในตอนท้ายของฉันฉันชอบที่จะมีวัตถุประวัติศาสตร์เดียวที่ฉันสามารถดำเนินการได้แม้กระทั่งองค์ประกอบภายนอก สิ่งที่ฉันชอบทำคือมีไฟล์ history.js ไฟล์เดียวที่ฉันนำเข้าแบบออนดีมานด์และจัดการมัน

คุณเพียงแค่ต้องเปลี่ยนBrowserRouterเป็น Router และระบุ prop ประวัติ สิ่งนี้จะไม่เปลี่ยนแปลงอะไรสำหรับคุณยกเว้นว่าคุณมีวัตถุประวัติของคุณเองที่คุณสามารถจัดการได้ตามที่คุณต้องการ

คุณต้องติดตั้งประวัติศาสตร์react-routerห้องสมุดที่ใช้โดย

ตัวอย่างการใช้งาน, สัญกรณ์ 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>;
    }
}

แก้ไข 16 เมษายน 2018:

หากคุณต้องนำทางจากองค์ประกอบที่แสดงผลมาจากRouteส่วนประกอบจริงๆคุณสามารถเข้าถึงประวัติจากอุปกรณ์ประกอบฉากเช่นว่า:

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 บอกเราคุณไม่ควรสำหรับกรณีส่วนใหญ่จำเป็นต้องใช้แทนRouter สร้างและรักษาวัตถุสำหรับคุณ คุณไม่ควรเริ่มต้นสร้างด้วยตัวคุณเองเฉพาะเมื่อคุณ ["จำเป็นต้องบูรณาการอย่างลึกซึ้งกับเครื่องมือการจัดการสถานะเช่น Redux"] reacttraining.com/react-router/web/api/RouterBrowserRouterBrowserRouterhistory
bobbyz

2
นั่นคือสิ่งที่ฉันได้เรียนรู้เมื่อเวลาผ่านไปและประสบการณ์ แม้ว่าโดยทั่วไปจะเป็นวิธีปฏิบัติที่ดีในการใช้ค่าเริ่มต้นthis.props.historyแต่ฉันยังไม่พบวิธีแก้ปัญหาที่สามารถช่วยฉันทำสิ่งนี้ในคลาสที่ไม่ใช่ส่วนประกอบหรือเครื่องมืออื่น ๆ ที่ไม่ได้สร้างขึ้นเป็นส่วนประกอบของปฏิกิริยา คุณสามารถส่งผ่านอุปกรณ์ประกอบฉาก ขอบคุณสำหรับคำติชมของคุณ :)
Eric Martin

44

สำหรับอันนี้ใครไม่ได้ควบคุมฝั่งเซิร์ฟเวอร์และเพราะสิ่งนี้ใช้แฮชเราเตอร์ v2:

วางประวัติของคุณเป็นไฟล์แยก (เช่น app_history.js ES6):

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

export default appHistory;

และใช้งานได้ทุกที่!

จุดเริ่มต้นของคุณสำหรับ react-router (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"]'));

การนำทางของคุณภายในองค์ประกอบใด ๆ (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
ขอบคุณ บางทีฉันอาจจะหายไปบางสิ่งบางอย่าง นี่ไม่เหมือนกันกับคำตอบสองอันดับแรกใช่หรือไม่
George Mauer

2
เมื่อคุณใช้การนำทาง "แฮช" ใน "react-router" v2 คุณต้องติดตั้งโมดูล "history" เพิ่มเติม (หากคุณต้องการหลีกเลี่ยงการแฮ็คข้อความแปลก ๆ ) และแทนที่จะใช้ browserHistory คุณต้องใช้ useRouterHistory (createHashHistory) ( {queryKey: false}) นี่คือเหตุผลหลักว่าทำไมฉันโพสต์นี้ ฉันแสดงวิธีการนำทางด้วยประวัติแฮช
Alexey Volodko

1
โอ้ฉันเข้าใจแล้วคุณพูดถูก ฉันไม่ได้อยู่ในโครงการนั้นอีกต่อไป แต่ฉันคิดว่าวิธีที่ต้องการคือใช้historyสำหรับวิธีใดวิธีหนึ่งในตอนนี้
George Mauer

4
ทำไมคำตอบนี้ไม่ดีที่สุด ทำไมต้องเผชิญกับปัญหาบริบทหรือ HOC หรือต้นแบบเหตุการณ์ทำไมไม่เพียงนำเข้าประวัติและใช้ทุกที่ที่เราต้องการ เพียงพยายามที่จะเข้าใจการแลกเปลี่ยน
storm_buster

@storm_buster ไม่มีข้อเสีย เรามีโมดูล ES6 และเราควรใช้มัน! นี่เป็นตัวอย่างที่แสดงให้เห็นถึงการใช้เครื่องมือของคุณ (ตอบสนองในกรณีนี้) สำหรับทุกสิ่ง - แม้กระทั่งสิ่งที่คุณไม่ต้องการใช้
Capaj

40

ทำปฏิกิริยาเราเตอร์ V4

TL: ดร;

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

คำตอบที่ง่ายและเปิดเผยคือคุณต้องใช้<Redirect to={URL} push={boolean} />ร่วมกับsetState()

push: บูลีน -เมื่อเป็นจริงการเปลี่ยนเส้นทางจะผลักรายการใหม่เข้าสู่ประวัติแทนการแทนที่รายการปัจจุบัน


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

ตัวอย่างเต็มรูปแบบที่นี่ อ่านเพิ่มเติมที่นี่

PS ตัวอย่างใช้ES7 + คุณสมบัติ Initializersเพื่อเริ่มต้นสถานะ ดูที่นี่เช่นกันหากคุณสนใจ


นี่คือคำตอบที่ดีที่สุดที่ฉันพบ การใช้withRouterไม่ทำงานเมื่ออยู่บนเส้นทางที่กำลังโหลดซ้ำ ในกรณีของเราเราต้องเลือกทำsetState(ทำให้return <Redirect>) ถ้าอยู่บนเส้นทางหรือhistory.push()จากที่อื่น
karmakaze

ฉลาดมาก ๆ และยังง่ายมาก Tks ฉันใช้ภายใน ReactRouterTable เพราะฉันต้องการจัดการคลิกบนบรรทัดทั้งหมด ใช้กับ onRowClick เพื่อตั้งค่าสถานะ setState ({นำทางTo: "/ path /" + row.uuid});
Lovato

นี่คือคำตอบที่พิสูจน์กระสุน
Nitin Jadhav

31

คำเตือน:คำตอบนี้ครอบคลุมเฉพาะรุ่น ReactRouter ก่อน 1.0

ฉันจะอัปเดตคำตอบนี้ด้วยกรณีการใช้ 1.0.0-rc1 หลังจาก!

คุณสามารถทำได้โดยไม่ต้องมิกซ์อินด้วย

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

gotcha พร้อมบริบทคือมันไม่สามารถเข้าถึงได้เว้นแต่คุณจะกำหนดcontextTypesบนคลาส

สำหรับบริบทคืออะไรมันเป็นวัตถุเช่นอุปกรณ์ประกอบฉากที่ถูกส่งลงมาจากพ่อแม่สู่ลูก แต่มันถูกส่งลงมาโดยปริยายโดยไม่ต้องประกาศอุปกรณ์ประกอบฉากในแต่ละครั้ง ดูhttps://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html


26

ฉันพยายามทำอย่างน้อย 10 วิธีก่อนที่จะมีบางอย่างทำงานถูกต้อง!

withRouterคำตอบของ @Felipe Skinner เป็นเรื่องยากสำหรับฉันและฉันไม่แน่ใจว่าฉันต้องการสร้างชื่อคลาส "ExportedWithRouter" ใหม่

นี่คือวิธีที่ง่ายและสะอาดที่สุดในการทำ React-Router 3.0.0 และ ES6 ในปัจจุบัน:

React-Router 3.xx พร้อม 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);

หรือหากไม่ใช่คลาสเริ่มต้นของคุณให้ส่งออกเช่น:

withRouter(Example);
export { Example };

โปรดทราบว่าใน 3.xx <Link>ส่วนประกอบกำลังใช้router.pushงานอยู่ดังนั้นคุณสามารถส่งผ่านสิ่งใดก็ได้ที่คุณจะผ่าน<Link to=แท็กเช่น:

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

1
มันใช้งานได้ดีโดยสิ้นเชิง แต่ตอบสนอง200 OKแทน30xรหัส ฉันจะแก้ไขปัญหานี้ได้อย่างไร
มูฮัมหมัด Ateeq Azam

1
ไม่แน่ใจ. สิ่งนี้ไม่เคยเกิดขึ้นกับฉันเพราะไม่ใช่คำขอภายนอก - เป็นเพียงเบราว์เซอร์ของคุณที่ใช้รหัสของหน้าเพื่อเปลี่ยนสิ่งที่อยู่บนหน้า คุณสามารถเปลี่ยนเส้นทางจาวาสคริปต์เองได้ทุกเมื่อที่ต้องการ
Ben Wheeler

1
มันยังสามารถใช้กับ @withRouter ในฐานะมัณฑนากรระดับ ... ไปได้ดีกับ mobx
Dan

21

ในการทำการนำทางโดยทางโปรแกรมคุณต้องผลักดันประวัติใหม่ไปยังอุปกรณ์ประกอบฉากประวัติของคุณcomponentดังนั้นสิ่งนี้จะช่วยคุณได้:

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

โปรดเขียนเวอร์ชันของ react-router
Ash

19

สำหรับส่วนประกอบ ES6 + React โซลูชันต่อไปนี้ใช้ได้สำหรับฉัน

ฉันติดตามเฟลิพเป้สกินเนอร์ แต่ได้เพิ่มการแก้ปัญหาแบบปลายถึงปลายเพื่อช่วยผู้เริ่มต้นเช่นฉัน

ด้านล่างนี้เป็นรุ่นที่ฉันใช้:

"react-router": "^ 2.7.0"

"ตอบสนอง": "^ 15.3.1"

ด้านล่างนี้เป็นองค์ประกอบการตอบสนองของฉันที่ฉันใช้การนำทางแบบโปรแกรมโดยใช้ 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;

ด้านล่างคือการกำหนดค่าสำหรับเราเตอร์ของฉัน:

 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

อาจไม่ใช่วิธีที่ดีที่สุด แต่ ... เมื่อใช้ react-router v4 ตัวพิมพ์ที่ต่อไปนี้อาจให้แนวคิดสำหรับบางคน

ในองค์ประกอบที่แสดงด้านล่างเช่นLoginPage, routerวัตถุสามารถเข้าถึงและเพียงแค่โทรrouter.transitionTo('/homepage')เพื่อนำทาง

รหัสนำทางที่ถูกนำมาจาก

"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
ทำไมคุณไม่ใช้กับเสื้อนอกและเบราว์เซอร์ประวัติ
Erwin Mayer

1
@Erwin API แตกต่างกันใน v4 ดูgithub.com/ReactTraining/react-router/issues/3847นี้
mcku

1
@mcku คุณได้รับไฟล์ typescript dts ของคุณสำหรับ react-router v4 ที่ไหน
jmathew

1
@ jmathew ฉันไม่มีคำจำกัดความประเภทใด ๆ สำหรับ react-router v4
mcku

16

ในReact-Router v4และES6

คุณสามารถใช้และwithRouterthis.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
กล่าวแล้วในคำตอบอื่น ๆ หลายคน (รวมทั้งที่มีความยาวในคำตอบด้านบน)
จอร์จ Mauer

13

หากต้องการใช้withRouterกับส่วนประกอบแบบคลาสให้ลองทำดังนี้ อย่าลืมเปลี่ยนคำสั่งส่งออกเพื่อใช้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 และ Ben Wheeler
สิ่งแปลกใหม่ จะเขียนในtypescript
และการใช้decorators
หรือคุณสมบัติ / เขต คงที่

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

ด้วยสิ่งที่ติดตั้ง NPM วันนี้ "react-router": "^ 3.0.0" และ
"@ types / react-router": "^ 2.0.41"


11

ด้วย React-Router v4 บนขอบฟ้าตอนนี้มีวิธีใหม่ในการทำเช่นนี้

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

react-legoเป็นแอพตัวอย่างที่แสดงวิธีใช้ / อัปเดต react-routerและรวมถึงตัวอย่างการทดสอบการใช้งานที่นำทางแอพ


5
นี่เป็นวิธีที่ยอดเยี่ยมสำหรับการใช้งานฟังก์ชั่นการเรนเดอร์ถึงแม้ว่าฉันสงสัยว่าจะนำทางจากบางสิ่งบางอย่างเช่นฮุกวงจรชีวิตหรือการเปลี่ยนถ่ายใหม่ได้อย่างไร
รูเบนมาร์ติเนซจูเนียร์

11

ในปฏิกิริยาของเราเตอร์ v4 ฉันติดตามสองเส้นทางนี้เพื่อกำหนดเส้นทางการเขียนโปรแกรม

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

หมายเลขสอง

แทนที่รายการปัจจุบันบนสแต็กประวัติ

หากต้องการรับประวัติในอุปกรณ์ประกอบฉากคุณอาจจำเป็นต้องห่อส่วนประกอบด้วย

withRouter


ขอบคุณ !! คำตอบที่ดีที่สุด
Taha Farooqui

9

หากคุณใช้แฮชหรือประวัติเบราว์เซอร์คุณสามารถทำได้

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

2
hashHistory.pushให้ไม่สามารถอ่านคุณสมบัติ "push" ของที่ไม่ได้กำหนด คุณนำเข้าสิ่งเหล่านี้จากที่ใด
ArchNoob

นำเข้า {hashHistory} จาก "react-router"; คุณสามารถนำเข้าได้ด้วยวิธีนี้ที่ด้านบน
Zaman Afzal

ฉันใช้ตัวอย่างรหัสจากไฟล์ saga redux ของฉันนำเข้าเหมือนกับที่คุณพูดและใช้มัน แต่ฉันได้รับ TypeError นั้น
ArchNoob

8

ด้วยเวอร์ชัน React ปัจจุบัน (15.3) ใช้this.props.history.push('/location');งานได้สำหรับฉัน แต่มันแสดงคำเตือนต่อไปนี้:

browser.js: 49 คำเตือน: [react-router] props.historyและ context.historyเลิกใช้แล้ว context.routerกรุณาใช้

และฉันแก้ไขมันโดยใช้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
สิ่งนี้ใช้ได้กับ V4 อืม ... ปิด ... มันจำเป็นต้องเป็นสิ่งนี้จริงๆแล้วcontext.router.history.push ('/ back-location');
velohomme

7

React-Router V4

หากคุณใช้เวอร์ชั่น 4 คุณสามารถใช้ไลบรารี่ของฉัน (ปลั๊กไร้ยางอาย) ที่คุณสามารถส่งการกระทำและทุกอย่างก็ใช้ได้!

dispatch(navigateTo("/aboutUs"));

trippler


5

ผู้ที่ประสบปัญหาในการใช้งานกับ react-router v4

นี่คือโซลูชันที่ใช้งานได้สำหรับการนำทางผ่านแอพ react จาก redux actions

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 หรือไฟล์ redux

import history from './history' 

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

ขอบคุณทุกความคิดเห็นนี้: ReactTraining problems comments


4

หากเกิดขึ้นกับคู่ RR4 w / redux ผ่านreact-router-reduxให้ใช้ตัวสร้างแอ็คชั่นการกำหนดเส้นทางจากreact-router-reduxเป็นตัวเลือกเช่นกัน

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)

หากใช้ redux thunk / saga เพื่อจัดการ async flow ให้อิมพอร์ตผู้สร้างแอ็คชันด้านบนในการดำเนินการ redux และขอให้ตอบสนองต่อส่วนประกอบโดยใช้ mapDispatchToProps อาจดีกว่า


1
react-router-reduxถูกเลิกใช้ / เก็บถาวรมาเป็นเวลานาน
oligofren

4

นอกจากนี้คุณยังสามารถใช้useHistoryเบ็ดในองค์ประกอบไร้สัญชาติ ตัวอย่างจากเอกสาร

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

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

หมายเหตุ: hooks ถูกเพิ่มเข้ามาreact-router@5.1.0และต้องการreact@>=16.8


1
เยี่ยมมากคุณสามารถสังเกตรุ่นปฏิกิริยาของเราเตอร์และปฏิกิริยาที่อ้างถึงได้หรือไม่ นี่คือการเปลี่ยนแปลงใหม่ที่ไม่สามารถใช้ได้เสมอ
George Mauer

3

คำตอบที่ถูกต้องสำหรับฉันในขณะที่เขียน

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

แต่คุณต้องเพิ่ม PropTypes ในองค์ประกอบของคุณ

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

อย่าลืมนำเข้า PropTypes

import PropTypes from 'prop-types';

โปรดเขียนเวอร์ชันของ react-router และสิ่งที่คุณนำเข้าจาก react-router
Ash

ไม่มีอะไรที่จะนำเข้าและนี่เป็นเวอร์ชั่น "react-router": "^ 4.2.0"
ผู้ดูแลเว็บ

3

อาจไม่ใช่วิธีที่ดีที่สุด แต่ทำให้งานเสร็จ:

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

โดยพื้นฐานแล้วตรรกะที่ผูกติดอยู่กับการกระทำหนึ่ง (ในกรณีนี้การลบโพสต์) จะเป็นการเรียกทริกเกอร์สำหรับการเปลี่ยนเส้นทาง สิ่งนี้ไม่เหมาะเพราะคุณจะเพิ่ม 'ทริกเกอร์' โหนด DOM ในมาร์กอัปของคุณเพื่อให้คุณสามารถโทรหาได้สะดวกเมื่อต้องการ นอกจากนี้คุณยังจะต้องโต้ตอบโดยตรงกับ DOM ซึ่งอาจไม่ต้องการส่วนประกอบใน React

อย่างไรก็ตามการเปลี่ยนเส้นทางประเภทนี้ไม่จำเป็นต้องใช้บ่อย ดังนั้นหนึ่งหรือสองลิงก์พิเศษที่ซ่อนอยู่ในมาร์กอัปส่วนประกอบของคุณจะไม่ทำร้ายมากโดยเฉพาะถ้าคุณให้ชื่อที่มีความหมายกับพวกเขา


คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงใช้สิ่งนี้ผ่านทางโซลูชันที่ได้รับการยอมรับ?
George Mauer

มันเป็นเพียงทางเลือกในการแก้ไขปัญหาที่กล่าวถึง ตามที่ระบุไว้แล้วไม่เหมาะ แต่ทำงานได้ดีสำหรับการเปลี่ยนเส้นทางแบบเป็นโปรแกรม
เรียบร้อย

2

สิ่งนี้ใช้ได้สำหรับฉันไม่จำเป็นต้องมีการนำเข้าพิเศษ:

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

แน่นอนว่าต้องมีการนำเข้าพิเศษ - ส่วนประกอบของคุณไม่ได้historyเพิ่มเข้าไปpropsเพียงอย่างเดียว ที่มาจาก HoC ที่คุณจะต้องนำเข้าเพื่อใช้ (ส่วนประกอบที่ส่งโดยตรงโดยRouteจะถูกห่อโดย HoC นั้นโดยอัตโนมัติ แต่แล้วคุณต้องนำเข้าสำหรับRoute... )
George Mauer

2

ใช้ hookrouter แทนทางเลือกที่ทันสมัยเพื่อตอบสนองเราเตอร์

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

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

เพื่อตอบคำถาม OP เกี่ยวกับการเชื่อมโยงผ่านช่องเลือกที่คุณสามารถทำได้:

navigate('/about');

FYI ผู้เขียนเองเรียกห้องสมุดนี้ว่า "พิสูจน์แนวคิด" และไม่มีกิจกรรมใด ๆ มาเกือบปี (มิถุนายน 2562)
MEMark

@EMEMark นั่นเป็นเพราะมันสมบูรณ์แบบอยู่แล้ว
StefanBob

ปัญหาที่เปิดอยู่ 38 เรื่องพร้อมกับความจริงที่ว่าเวอร์ชั่น 2.0 จะเป็นการเขียนใหม่ที่สมบูรณ์แบบ
MEMark

1

สำหรับ React Router v4 +

สมมติว่าคุณไม่จำเป็นต้องนำทางในระหว่างการเรนเดอร์ตัวเอง (ซึ่งคุณสามารถใช้<Redirect>องค์ประกอบ) นี่คือสิ่งที่เรากำลังทำในแอปของเรา

กำหนดเส้นทางที่ว่างเปล่าซึ่งส่งคืนค่าว่างซึ่งจะทำให้คุณสามารถเข้าถึงวัตถุประวัติได้ คุณต้องทำสิ่งนี้ที่ระดับบนสุดของคุณRouterกำหนดไว้

ตอนนี้คุณสามารถทำสิ่งที่สามารถทำได้ในประวัติศาสตร์เช่นhistory.push(), history.replace(), history.go(-1)ฯลฯ !

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

react-router-dom: 5.1.2

  • ไซต์นี้มี 3 หน้าซึ่งทั้งหมดแสดงผลแบบไดนามิกในเบราว์เซอร์

  • แม้ว่าหน้าเว็บจะไม่รีเฟรชเลย แต่ให้สังเกตว่า React Router รักษา URL ให้ทันสมัยอยู่เสมอในขณะที่คุณสำรวจเว็บไซต์ สิ่งนี้จะรักษาประวัติเบราว์เซอร์ทำให้แน่ใจว่าสิ่งต่าง ๆ เช่นปุ่มย้อนกลับและบุ๊กมาร์กทำงานได้อย่างถูกต้อง

  • สวิทช์ดูผ่านทุกองค์ประกอบของเด็กและวาทกรรมคนแรกที่มีเส้นทางตรง URL ปัจจุบัน ใช้เวลาใดก็ได้ที่คุณมีหลายเส้นทาง แต่คุณต้องการให้แสดงเพียงเส้นทางเดียวในแต่ละครั้ง

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! เมื่อคุณตอบคำถามด้วยคำตอบมากมายพยายามแสดงให้เห็นถึงประโยชน์ของคุณ
David García Bodego

สิ่งนี้ยังไม่ตอบคำถามซึ่งเป็นวิธีการเขียนโปรแกรมจาก js ที่จำเป็นไม่ใช่ด้วยมาร์กอัป
George Mauer

1

ดังนั้นในคำตอบของฉันมี 3 วิธีที่แตกต่างกันในการเปลี่ยนเส้นทางโปรแกรมไปยังเส้นทาง โซลูชันบางตัวได้รับการนำเสนอแล้ว แต่สิ่งต่อไปนี้เน้นเฉพาะส่วนประกอบที่ใช้งานได้พร้อมกับแอปพลิเคชันเพิ่มเติม

ใช้รุ่นต่อไปนี้:

ตอบสนอง: 16.13.1

react-dom: 16.13.1

react-router: 5.2.0

react-router-dom: 5.2.0

typescript: 3.7.2

การกำหนดค่า:

ดังนั้นก่อนอื่นให้ใช้วิธีแก้ปัญหาHashRouterกำหนดค่าดังนี้

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

จากเอกสารเกี่ยวกับ<HashRouter>:

A <Router>ที่ใช้ส่วนแฮชของ URL (เช่นwindow.location.hash) เพื่อให้ UI ของคุณซิงค์กับ URL

Solutions:

  1. ใช้<Redirect>เพื่อผลักดันโดยใช้useState:

ใช้ในองค์ประกอบการทำงาน ( RedirectPushActionส่วนประกอบจากพื้นที่เก็บข้อมูลของฉัน) เราสามารถใช้useStateเพื่อจัดการการเปลี่ยนเส้นทาง ส่วนที่ยุ่งยากเป็นอีกการเปลี่ยนเส้นทางที่เกิดขึ้นเราต้องตั้งรัฐกลับไปredirect falseโดยใช้setTimeOutกับ0ความล่าช้าที่เรากำลังรอจนกว่า React กระทำRedirectเพื่อ DOM แล้วเดินทางกลับปุ่มเพื่อใช้ในครั้งต่อไป

โปรดหาตัวอย่างของฉันด้านล่าง:

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

จาก<Redirect>เอกสาร:

การแสดงผล<Redirect>จะนำทางไปยังตำแหน่งใหม่ ตำแหน่งใหม่จะแทนที่ตำแหน่งปัจจุบันในสแต็กประวัติเช่นการเปลี่ยนเส้นทางฝั่งเซิร์ฟเวอร์ (HTTP 3xx) ทำ

  1. ใช้useHistoryเบ็ด:

ในโซลูชันของฉันมีส่วนประกอบที่เรียกว่าUseHistoryActionซึ่งแสดงถึงสิ่งต่อไปนี้:

let history = useHistory();

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

useHistoryเบ็ดจะช่วยให้เราสามารถเข้าถึงวัตถุประวัติศาสตร์ที่ช่วยให้เราเขียนโปรแกรมนำทางหรือการเปลี่ยนแปลงเส้นทาง

  1. ใช้withRouterรับhistoryจากprops:

สร้างส่วนประกอบหนึ่งที่เรียกว่าWithRouterActionแสดงดังต่อไปนี้:

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

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

export default withRouter(WithRouterAction);

อ่านจากwithRouterเอกสาร:

คุณสามารถเข้าถึงhistoryคุณสมบัติของวัตถุและการ<Route>จับคู่ที่ใกล้เคียงที่สุดผ่านwithRouterส่วนประกอบลำดับสูงกว่า withRouterจะผ่านการปรับปรุงmatch,locationและhistoryอุปกรณ์ประกอบฉากองค์ประกอบห่อเมื่อใดก็ตามที่จะแสดงผล

การสาธิต:

เพื่อเป็นตัวแทนที่ดีกว่าฉันได้สร้างที่เก็บ GitHub ด้วยตัวอย่างเหล่านี้โปรดค้นหาได้ที่ด้านล่าง:

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

ฉันหวังว่านี่จะช่วยได้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.