I want to define a URL that could be used to logout the user (dispatch an action that would logout the user). I have not found examples showing how to implement a route dispatching an event.
Asked
Active
Viewed 3.2k times
12
-
Why not just dispatch an action on a link click? Special route for logout is not necessary – just-boris Jan 11 '16 at 13:50
-
From the user's standpoint of view, I'd like to be able to access the logout function using an URL. – Gajus Jan 11 '16 at 14:33
-
I guess if you have Redux, that you are working on a single-page-application, that can't work with Javascript. So, what's the point to have an exposed link for it? – just-boris Jan 11 '16 at 15:22
-
2Again, as a "power user", I like to type URLs to perform operations such as being able to destroy my session. Whether the app is SPA or not, has little to do with it. – Gajus Jan 11 '16 at 15:49
-
Well, just go to `/api/logout` page or something like this, that does actual logout on the backend – just-boris Jan 11 '16 at 18:01
-
1The "session" persists on the client side (`window.localStorage`). Thats a standard JSON Web Token authentication implementation. Backend is not aware of user session. REST, by definition, is stateless (https://en.wikipedia.org/wiki/Representational_state_transfer#Stateless). – Gajus Jan 11 '16 at 18:42
-
Then your solution seems reasonable. [This example](https://github.com/rackt/react-router/blob/latest/examples/auth-flow/app.js#L129) in the React-router repo does the same. Redux-simple-router is a simple connector and doesn't have anything to help here. – just-boris Jan 11 '16 at 19:03
3 Answers
11
Here is a more current implementation for such /logout
page:
import { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import * as authActionCreators from '../actions/auth'
class LogoutPage extends Component {
componentWillMount() {
this.props.dispatch(authActionCreators.logout())
this.props.router.replace('/')
}
render() {
return null
}
}
LogoutPage.propTypes = {
dispatch: PropTypes.func.isRequired,
router: PropTypes.object.isRequired
}
export default withRouter(connect()(LogoutPage))
Diego V
- 5,021
- 6
- 34
- 43
-
-
agree - I would not say this is a more current implementation but an alternative implementation using `react-router` over `redux-simple-router`.I assume this would fit most use cases using `react-router` which is more commonly used and includes the 'withRouter' functionality which was recently introduced, so why the comment. :-) – markyph Jul 20 '16 at 07:39
-
First, please note that this implementation will work both with or without redux-simple-router (which, by the way, was renamed to react-router-redux a while ago). You can use Redux-style actions if you like, but it's not needed and IMHO it's not strictly related to the original routing problem. This implementation also takes advantage of the recently introduced `withRouter` higher-order component to make it simpler :) – Diego V Jul 20 '16 at 09:30
-
withRouter should be around connect, not the other way around (to prevent screen refresh problems) – Marc Sep 14 '17 at 19:41
-
-
Sure, react-router uses global context to navigate, this means that a navigation event doesn't impact `props` and therefore, a pure component wouldn't know it has to re-render. This means that you can navigate and "nothing happens". In order to prevent this, you can use withRouter, which supplies the location prop. This prop changes in case of a navigation event, the child React component will therefore re-render. That is why it has to be around the connect call, and not the other way around. – Marc Sep 16 '17 at 20:00
9
Define a route /authentication/logout
:
import React from 'react';
import {
Route,
IndexRoute
} from 'react-router';
import {
HomeView,
LoginView,
LogoutView
} from './../views';
export default <Route path='/'>
<IndexRoute component={HomeView} />
<Route path='/authentication/logout'component={LogoutView} />
<Route path='/authentication/login' component={LoginView} />
</Route>;
Create a LogoutView
that dispatches an action upon componentWillMount
:
import React from 'react';
import {
authenticationActionCreator
} from './../actionCreators';
import {
connect
} from 'react-redux';
import {
pushPath
} from 'redux-simple-router';
let LogoutView;
LogoutView = class extends React.Component {
componentWillMount () {
this.props.dispatch(authenticationActionCreator.logout());
this.props.dispatch(pushPath('/'));
}
render () {
return null;
}
};
export default connect()(LogoutView);
The componentWillMount
callback dispatches two actions:
- To destroy user session.
- To redirect user to the
IndexRoute
.
this.props.dispatch(authenticationActionCreator.logout());
this.props.dispatch(pushPath('/'));
Gajus
- 55,791
- 58
- 236
- 384
-
I am not 100% sure whether thats how the logout scenario should be handled. Please suggest an edit or add your answer if this is not a canonical approach. – Gajus Jan 11 '16 at 11:12
-
It would be better to split `logout` and `pushPath` actions. `pushPath` should be in `componentDidMount` – just-boris Jan 11 '16 at 19:06
-
-
2To make things go right. Some components may also want to update and upon logout, but you are firing a route change immediately. It was only my personal point of view if you don't have issues here, that is okay to leave it as is. – just-boris Jan 12 '16 at 16:18
-
-
Probably should redirect after upon success ( if there is any server call ). We need some types of promise. – Sisir Jul 06 '17 at 07:49
7
Here is the most current implementation for /logout
page:
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
import * as authActionCreators from "../actions/auth";
class LogoutPage extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired
};
componentWillMount() {
this.props.dispatch(authActionCreators.logout());
}
render() {
return (
<Redirect to="/" />
);
}
}
export default connect()(LogoutPage);
Works for:
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-redux": "^5.0.6",
"react-router-dom": "^4.2.2",
"prop-types": "^15.5.10",
billzhong
- 1,306
- 10
- 8