如何使用react-router重定向到另一个路由?


94

我正在尝试使用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'就是这样。

我能做什么 ?

控制台错误:

未捕获的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在5分钟内更改api。.哈哈,开玩笑,但只是部分
aarosil 2016年

Answers:


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中函数
2016年

5
您也可以在JSX中执行此操作{validation && <Link to="/login" />Click to login</Link>}。如果验证为假,则不会呈现任何内容。
aarosil

我知道您的意思,但我需要按钮在那里,如果验证为true,则重定向,否则将出现错误消息。
反应

@TheUnnamed我更新了答案以显示在JS中的操作
aarosil

1
>未捕获的TypeError:无法读取未定义的属性“ pushState”
反应

92

1)react-router> V5 useHistory挂钩:

如果您具有React >= 16.8功能组件,则可以使用useHistory react-router中钩子

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)react-router> V4 withRouterHOC:

正如@ambar在评论中提到的那样,自V4起,React-router更改了代码库。以下是本细则- 官方withRouter

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)反应路由器<V4与 browserHistory

您可以使用react-router实现此功能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连接,并配置了connected-react-routerthis.props.history.push("/new/url");withRouter则只需要做的就是, 即无需HOC即可注入history组件prop。

// 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的一部分。
安巴尔

BrowserRouter没有推送功能
johnnyodonnell

@ambar @johnnyodonnell react-router-dom确实
toinetoine

这是最好的答案。您应该将此标记为正确的。
所罗门·布什

23

如何使用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:字符串,重定向到的URL。

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

to:对象,重定向到的位置。

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

提供的解决方案将引发错误<Redirect> elements are for router configuration only and should not be rendered
t1gor

9

最简单的网络解决方案!


确认到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指出“无法解析符号...”警告,它也可以正常工作!
拉斐尔·莫尼

7

使用react-router v2.8.1(可能还有其他2.xx版本,但我尚未测试过),您可以使用此实现来进行Router重定向。

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');
象嘉道

4

最简单的解决方案是:

import { Redirect } from 'react-router';

<Redirect to='/componentURL' />

但是我遇到一个错误:不变失败:您不应该在<Router>之外使用<Redirect>
Prateek Gupta

你试着包好吗?
Jackkobec
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.