React Router 5. Component not rendered after redirect

Viewed 315

I'm trying to implement redirect to login page and then to profile page after successful login.

When I do

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

Redirect to login page doesn't work. However it works if I use BrowserRouter:

import { BrowserRouter as Router } from 'react-router-dom';

As per info from quick goolgling, Browser router doesn't work with histry.push, which I need to use after successful login.

What I'm doing wrong?

history:

import { createBrowserHistory } from 'history';

const history = createBrowserHistory();
export default history;

App.js:

//...
import { Router, Route, Switch } from 'react-router-dom'; // redirects if using BrowserRouter as Router
import history from './helpers/history';
//...

function App() {
  return (
    <div className="App">
      <Router history={history}>
        <Switch>
          <PrivateRoute exact path={process.env.REACT_APP_ROUTE_PREFIX} component={ProfilePage} />
          <Route path={`${process.env.REACT_APP_ROUTE_PREFIX}/login`} component={LoginPage} />
        </Switch>
      </Router>
    </div>
  );
}
export default App;

index.js:

// ...
ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

PrivateRoute.jsx:

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

const PrivateRoute = withRouter(({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
        localStorage.getItem('user')
            ? <Component {...props} />
            : <Redirect to={{ pathname: `${process.env.REACT_APP_ROUTE_PREFIX}/login`, 
                        state: { from: props.location } }} />
    )} />
))

after login:

import history from '../../helpers/history'
//...
// thunk
export const login = (username, password) => dispatch => {
    dispatch(request({ username }));

    authClient.login(username, password)
        .then(
            user => {
                dispatch(success(user));
                // updates the url, but doesn't get caught by BrowserRouter
                // useHistory doesn't work here as it's for stateless components
                history.push(process.env.REACT_APP_ROUTE_PREFIX); 
            },
            error => {
                dispatch(failure(error));
            }
        );
}

modules versions:

    "history": "^5.0.0",
    "react-router-dom": "^5.2.0",

LoginPage and ProfilePage are also wrapped with withRouter

1 Answers

Okay, I solved it by using history from the LoginPage properties:

export const login = (username, password, history) => dispatch => {
   //...
   history.push(process.env.REACT_APP_ROUTE_PREFIX);
   //...
}
    handleSubmit(e) {
        e.preventDefault();

        this.setState({ submitted: true });
        const { username, password } = this.state;
        const { dispatch, history } = this.props;
        if (username && password) {
            dispatch(login(username, password, history));
        }
    }

I'm not sure if it's a good approach. Can anyone advice?

Related