จะเปลี่ยนเส้นทางไปยังเส้นทางอื่นด้วย react-router ได้อย่างไร?


102

ฉันกำลังพยายามทำ A SIMPLE โดยใช้ react-router ( เวอร์ชัน ^ 1.0.3 ) เพื่อเปลี่ยนเส้นทางไปยังมุมมองอื่นและฉันก็เหนื่อย

import React from 'react';
import {Router, Route, Link, RouteHandler} from 'react-router';


class HomeSection extends React.Component {

  static contextTypes = {
    router: PropTypes.func.isRequired
  };

  constructor(props, context) {
    super(props, context);
  }

  handleClick = () => {
    console.log('HERE!', this.contextTypes);
    // this.context.location.transitionTo('login');
  };

  render() {
    return (
      <Grid>
        <Row className="text-center">          
          <Col md={12} xs={12}>
            <div className="input-group">
              <span className="input-group-btn">
                <button onClick={this.handleClick} type="button">
                </button>
              </span>
            </div>
          </Col>
        </Row>
      </Grid>
    );
  }
};

HomeSection.contextTypes = {
  location() {
    React.PropTypes.func.isRequired
  }
}

export default HomeSection;

สิ่งที่ฉันต้องการคือส่งการใช้งานไปที่ '/ login' เท่านี้

ฉันจะทำอะไรได้บ้าง?

ข้อผิดพลาดในคอนโซล:

Uncaught ReferenceError: PropTypes ไม่ได้กำหนดไว้

ไฟล์ด้วยเส้นทางของฉัน

// LIBRARY
/*eslint-disable no-unused-vars*/
import React from 'react';
/*eslint-enable no-unused-vars*/
import {Route, IndexRoute} from 'react-router';

// COMPONENT
import Application from './components/App/App';
import Contact from './components/ContactSection/Contact';
import HomeSection from './components/HomeSection/HomeSection';
import NotFoundSection from './components/NotFoundSection/NotFoundSection';
import TodoSection from './components/TodoSection/TodoSection';
import LoginForm from './components/LoginForm/LoginForm';
import SignupForm from './components/SignupForm/SignupForm';

export default (
    <Route component={Application} path='/'>
      <IndexRoute component={HomeSection} />
      <Route component={HomeSection} path='home' />
      <Route component={TodoSection} path='todo' />
      <Route component={Contact} path='contact' />
      <Route component={LoginForm} path='login' />
      <Route component={SignupForm} path='signup' />
      <Route component={NotFoundSection} path='*' />
    </Route>
);

ไฮ! คุณสามารถโพสต์routesคำจำกัดความของคุณและมีเหตุผลที่คุณไม่ได้ใช้Linkส่วนประกอบหรือไม่? นอกจากนี้ให้ระบุข้อผิดพลาดที่คุณได้รับ
aarosil

แทนที่จะเป็นปุ่ม<Link to="/login">Log In</Link>?
aarosil

คุณใช้ react-router รุ่นอะไรอยู่? รหัสสำหรับการเปลี่ยนเส้นทางตามขั้นตอนมีการเปลี่ยนแปลงระหว่างเวอร์ชันหลัก ๆ
mjhm

4
สำหรับUncaught ReferenceErrorคุณกำลังโทรเป็นPropTypesแต่คุณไม่ได้นำเข้าคุณต้องนำเข้า PropTypes เป็นของตัวเองหรือใช้React.PropTypes
aarosil

1
@JoshDavidMiller เป็นจุดที่ดี แต่ฉันจะไม่react-routerเปลี่ยน api อย่างน่าประหลาดใจภายใน 5 นาที .. ฮ่าฮ่าล้อเล่น แต่แค่บางส่วน
aarosil

คำตอบ:


33

สำหรับคำตอบง่ายๆที่คุณสามารถใช้Linkส่วนประกอบจากแทนreact-router buttonมีหลายวิธีในการเปลี่ยนเส้นทางใน JS แต่ดูเหมือนว่าคุณไม่จำเป็นต้องใช้ที่นี่

<span className="input-group-btn">
  <Link to="/login" />Click to login</Link>
</span>

หากต้องการทำแบบเป็นโปรแกรมใน 1.0.x ให้ทำดังนี้ภายในฟังก์ชัน clickHandler ของคุณ:

this.history.pushState(null, 'login');

นำมาจากเอกสารการอัปเกรดที่นี่

คุณควรจะได้วางไว้ในส่วนเส้นทางของคุณโดยการจัดการthis.history react-routerหากเป็นองค์ประกอบลูกที่อยู่ภายใต้ที่กล่าวถึงในroutesคำจำกัดความคุณอาจต้องผ่านสิ่งนั้นต่อไป


2
นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยม แต่สาเหตุที่ฉันไม่ได้ใช้มันเป็นเพราะฉันต้องทำการตรวจสอบความถูกต้องก่อนดังนั้นฉันจึงต้องใส่สิ่งนี้ในฟังก์ชันเช่น: if (true) { // redirect to login}นั่นคือเหตุผลที่ฉันใส่สิ่งนั้นใน onClick ฟังก์ชัน
ตอบสนอง

5
นอกจากนี้คุณยังสามารถทำใน {validation && <Link to="/login" />Click to login</Link>}JSX: หากการตรวจสอบความถูกต้องเป็นเท็จจะไม่มีการแสดงผล
aarosil

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

@TheUnnamed ฉันอัปเดตคำตอบเพื่อแสดงวิธีการทำใน JS
aarosil

1
> Uncaught TypeError: ไม่สามารถอ่านคุณสมบัติ 'pushState' ของ undefined
ตอบสนอง

109

1) react-router> V5 useHistoryhook:

ถ้าคุณมีReact >= 16.8และส่วนประกอบการทำงานคุณสามารถใช้เบ็ดจากตอบสนองเราเตอร์useHistory

import React from 'react';
import { useHistory } from 'react-router-dom';

const YourComponent = () => {
    const history = useHistory();

    const handleClick = () => {
        history.push("/path/to/push");
    }

    return (
        <div>
            <button onClick={handleClick} type="button" />
        </div>
    );
}

export default YourComponent;

2) ตอบสนองเราเตอร์> V4 withRouterHOC:

ดังที่ @ambar กล่าวไว้ในความคิดเห็น React-router ได้เปลี่ยนฐานรหัสตั้งแต่ V4 นี่คือเอกสาร - อย่างเป็นทางการกับเราเตอร์

import React, { Component } from 'react';
import { withRouter } from "react-router-dom";

class YourComponent extends Component {
    handleClick = () => {
        this.props.history.push("path/to/push");
    }

    render() {
        return (
            <div>
                <button onClick={this.handleClick} type="button">
            </div>
        );
    };
}

export default withRouter(YourComponent);

3) React-router <V4 กับ browserHistory

BrowserHistoryคุณสามารถบรรลุการทำงานนี้ใช้ตอบสนองเราเตอร์ รหัสด้านล่าง:

import React, { Component } from 'react';
import { browserHistory } from 'react-router';

export default class YourComponent extends Component {
    handleClick = () => {
        browserHistory.push('/login');
    };

    render() {
        return (
            <div>
                <button onClick={this.handleClick} type="button">
            </div>
        );
    };
}

4) Redux connected-react-router

หากคุณเชื่อมต่อคอมโพเนนต์ของคุณกับ redux และได้กำหนดค่าคอนเน็กเตอร์ - ตอบสนอง - เราเตอร์สิ่งที่คุณต้องทำก็ this.props.history.push("/new/url");คือคุณไม่จำเป็นต้องใช้withRouterHOC เพื่อฉีดhistoryเข้าไปในอุปกรณ์ประกอบฉาก

// reducers.js
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';

export default (history) => combineReducers({
    router: connectRouter(history),
    ... // rest of your reducers
});


// configureStore.js
import { createBrowserHistory } from 'history';
import { applyMiddleware, compose, createStore } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import createRootReducer from './reducers';
...
export const history = createBrowserHistory();

export default function configureStore(preloadedState) {
    const store = createStore(
        createRootReducer(history), // root reducer with router state
        preloadedState,
        compose(
            applyMiddleware(
                routerMiddleware(history), // for dispatching history actions
                // ... other middlewares ...
            ),
        ),
    );

    return store;
}


// set up other redux requirements like for eg. in index.js
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router';
import { ConnectedRouter } from 'connected-react-router';
import configureStore, { history } from './configureStore';
...
const store = configureStore(/* provide initial state if any */)

ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <> { /* your usual react-router v4/v5 routing */ }
                <Switch>
                    <Route exact path="/yourPath" component={YourComponent} />
                </Switch>
            </>
        </ConnectedRouter>
    </Provider>,
    document.getElementById('root')
);


// YourComponent.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
...

class YourComponent extends Component {
    handleClick = () => {
        this.props.history.push("path/to/push");
    }

    render() {
        return (
          <div>
            <button onClick={this.handleClick} type="button">
          </div>
        );
      }
    };

}

export default connect(mapStateToProps = {}, mapDispatchToProps = {})(YourComponent);

3
ดูเหมือนว่า 'browserHistory' ไม่ได้เป็นส่วนหนึ่งของ react-router อีกต่อไป
ambar

BrowserRouter ไม่มีฟังก์ชันพุช
johnnyodonnell

@ambar @johnnyodonnell react-router-domทำ
toinetoine

นี่คือคำตอบที่ดีที่สุด คุณควรทำเครื่องหมายอันนี้ว่าถูกต้อง
Solomon Bush

24

จะเปลี่ยนเส้นทางไปยังเส้นทางอื่นด้วย react-router ได้อย่างไร?

ตัวอย่างเช่นเมื่อผู้ใช้คลิกลิงค์<Link to="/" />Click to route</Link>react-router จะค้นหา/และคุณสามารถใช้Redirect toและส่งผู้ใช้ไปที่อื่นเช่นเส้นทางการเข้าสู่ระบบ

จากเอกสารสำหรับReactRouterTraining :

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

import { Route, Redirect } from 'react-router'

<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>

to: string, URL ที่จะเปลี่ยนเส้นทางไป

<Redirect to="/somewhere/else"/>

ถึง: object, ตำแหน่งที่จะเปลี่ยนเส้นทางไป

<Redirect to={{
  pathname: '/login',
  search: '?utm=your+face',
  state: { referrer: currentLocation }
}}/>

<Redirect> elements are for router configuration only and should not be renderedวิธีการแก้ปัญหาที่มีให้โยนข้อผิดพลาด
t1gor

12

ทางออกที่ง่ายที่สุดสำหรับเว็บ!

ถึงวันที่ 2020
ยืนยันว่าทำงานร่วมกับ:

"react-router-dom": "^5.1.2"
"react": "^16.10.2"

ใช้useHistory()เบ็ด!

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


export function HomeSection() {
  const history = useHistory();
  const goLogin = () => history.push('login');

  return (
    <Grid>
      <Row className="text-center">          
        <Col md={12} xs={12}>
          <div className="input-group">
            <span className="input-group-btn">
              <button onClick={goLogin} type="button" />
            </span>
          </div>
        </Col>
      </Row>
    </Grid>
  );
}

ยอดเยี่ยมกำลังมองหาวิธีเบ็ดที่จะทำ! แม้ว่า IDE ของฉันจะระบุคำเตือน "ไม่สามารถแก้ไขสัญลักษณ์ ... " ได้ แต่ก็ใช้งานได้!
Rafael Moni

เยี่ยมมากนั่นคือสิ่งที่ฉันกำลังมองหาและใช้งานได้ที่นี่
nanquim

7

ด้วย react-router v2.8.1 (อาจเป็นเวอร์ชัน 2.xx อื่น ๆ เช่นกัน แต่ฉันยังไม่ได้ทดสอบ) คุณสามารถใช้การใช้งานนี้เพื่อทำการเปลี่ยนเส้นทางเราเตอร์

import { Router } from 'react-router';

export default class Foo extends Component {

  static get contextTypes() {
    return {
      router: React.PropTypes.object.isRequired,
    };
  }

  handleClick() {
    this.context.router.push('/some-path');
  }
}

บางครั้ง: this.context.router.history.push ('/ some-path');
象嘉道

5

ทางออกที่ง่ายที่สุดคือ:

import { Redirect } from 'react-router';

<Redirect to='/componentURL' />

แต่ฉันได้รับข้อผิดพลาด: Invariant ล้มเหลว: คุณไม่ควรใช้ <Redirect> นอก <Router>
Prateek Gupta

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