How to do a redirect to another route with react-router?

I am trying to do A SIMPLE using react-router ( version ^1.0.3 ) to redirect to another view.

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;

all I need is to send the use to '/login' and that's it.

What can I do ?

errors in console:

Uncaught ReferenceError: PropTypes is not defined

file with my routes

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

8 Answers

1) react-router > V6 useNavigate hook:

If you have React >= 16.8 and functional components you can use the useNavigate hook from react-router.

import React from 'react';
import { useNavigate } from "react-router-dom";
const YourComponent = () => { const navigate = useNavigate(); const handleClick = () => { navigate("/path/to/push"); } return ( <div> <button onClick={handleClick} type="button" /> </div> );
}
export default YourComponent;

2) react-router > V5 useHistory hook:

If you have react-router v5 and functional components you can use the useHistory hook from 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;

3) react-router > V4 withRouter HOC:

As @ambar mentioned in the comments, React-router has changed its codebase since its V4. Here is the documentation for 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);

4) React-router < V4 with browserHistory

You can achieve this functionality using react-router BrowserHistory. Code below:

import React, { Component } from 'react';
import { browserHistory } from 'react-router-dom';
export default class YourComponent extends Component { handleClick = () => { browserHistory.push('/login'); }; render() { return ( <div> <button onClick={this.handleClick} type="button"> </div> ); };
}

5) Redux connected-react-router

If you have connected your component with redux, and have configured connected-react-router all you have to do isthis.props.history.push("/new/url"); ie, you don't need withRouter HOC to inject history to the component props.

// 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-dom';
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);
6

For the simple answer, you can use Link component from react-router, instead of button. There is ways to change the route in JS, but seems you don't need that here.

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

To do it programmatically in 1.0.x, you do like this, inside your clickHandler function:

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

Taken from upgrade doc here

You should have this.history placed on your route handler component by react-router. If it child component beneath that mentioned in routes definition, you may need pass that down further

9

How to do a redirect to another route with react-router?

For example, when a user clicks a link <Link to="/" />Click to route</Link> react-router will look for / and you can use Redirect to and send the user somewhere else like the login route.

From the docs for ReactRouterTraining:

Rendering a <Redirect> will navigate to a new location. The new location will override the current location in the history stack, like server-side redirects (HTTP 3xx) do.

import { Route, Redirect } from 'react-router'
<Route exact path="/" render={() => ( loggedIn ? ( <Redirect to="/dashboard"/> ) : ( <PublicHomePage/> )
)}/>

to: string, The URL to redirect to.

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

to: object, A location to redirect to.

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

Easiest solution for web!

Up to date 2020
confirmed working with:

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

Use the useHistory() hook!

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

I know this is an old question, but for whoever comes here in 2021 and after as of React Router V6 useHistory is no longer exported from react-router-dom and you have to import useNavigate instead. Sample code is below:

import { useNavigate } from "react-router-dom"

and inside your react class or functional component:

const navigate = useNavigate()
navigate("/404")

With react-router v2.8.1 (probably other 2.x.x versions as well, but I haven't tested it) you can use this implementation to do a Router redirect.

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

The simplest solution is:

import { Redirect } from 'react-router';
<Redirect to='/componentURL' />
2

Update for react-router-dom version >= 6

useHistory has been replaced by useNavigate.

You can use useNavigate as follows:

import {useNavigate} from 'react-router-dom';
const navigate = useNavigate();
navigate('/login');

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like