1

I use BrowserRouter in my React/Redux app, so I don't create history object nor pass it to BrowserRouter, as it handles its own history. At the moment, I mocked login functionality, and this is function in Login component (which calls login thunk in authActions):

handleSubmit = (e) => {
        e.preventDefault();

        this.props.authActions.login({
            email: this.state.email,
            password: this.state.password
        });
    };

AuthActions are mapped to component props:

function mapDispatchToProps(dispatch) {
    return {
        authActions: bindActionCreators(authActions, dispatch)
    }
}

And this is login thunk in authActions:

export function login(userData) {
    return function (dispatch) {
        if(userData.email === 'test@test.com' && userData.password === 'pw'){
            sessionStorage.setLoggedUser(JSON.stringify(userData));
            dispatch(loginSuccess(userData));
            this.context.router.history.push('/');
        } else {
            dispatch(loginFail());
        }
    }
}

I get error that context is undefined, but after successful Login, app navigates to "/" route. I passed context as second parameter to constructor and super methods in Login component.

class Login extends Component {
    constructor(props, context) {
        super(props, context);

Now, my question is. What is the best place to do location changes? Component itself, or in actions (thunks)? I mention thunks for purpose, as I will change code and have some async calls to backend. How to access history object when using `BrowserRouter, in both component and actions bound to it?

julienc
  • 19,087
  • 17
  • 82
  • 82
  • use withRouter from react-router-dom. ex: https://stackoverflow.com/questions/51477910/redirect-react-router-from-context-provider/51478324#51478324 – Srinivas Jul 24 '18 at 07:53
  • In order to access history in actions, you either need to pass it from the component while dispatching action or you can create a history object, Please Refer https://stackoverflow.com/questions/48514773/use-history-push-in-action-creator-with-react-router-v4/48514877?noredirect=1#comment89952323_48514877 for more details – Shubham Khatri Jul 24 '18 at 08:07
  • Also accessing router from context isn't supported in react-router-v4, you can have a look at this answer https://stackoverflow.com/questions/44127739/programmatically-navigate-using-react-router/44128108#44128108 – Shubham Khatri Jul 24 '18 at 08:08

1 Answers1

1

my suggestion is: change location in componentDidMount lifecycle hook.

you have there some props to compare, make some actions etc...

https://reactjs.org/docs/react-component.html#componentdidmount.

even better when you create HOC for managing location changes

UPDATE

first, NO change location in render func, this will generate error.

there any many many soloutins, based on your app structure... another solution is use 'componentWillReceiveProps'

componentWillReceiveProps(nextProps, nextState){
  if(nextProps.isLoggedIn===true&&this.props.isLoggedIn===false){
    nextProps.history.push('path_for_logged_in')
  }
}

for access history in props, you need wrap your component with withRouter HOC

import { withRouter } from 'react-router'


withRouter(YourComponent)
dvvtms
  • 627
  • 3
  • 10
  • Can't change location in `componentDidMount` because location should be changed immediatelly after correct credentials on Login, in other words after dispatching `successful login` action. So it should be in action(thunk) or in component's login function, which is called on click. So lifecycle hook is not solution. –  Jul 24 '18 at 08:00