Keep your session sync with your local storage and Redux 🔑
Redux React Session provides an API that allows to manage sessions through the app, with authorization function for react-router and a persisted session.
yarn:
yarn add redux-react-session
npm:
npm install redux-react-session --save
- Add the session reducer:
import { combineReducers } from 'redux';
import { sessionReducer } from 'redux-react-session';
const reducers = {
// ... your other reducers here ...
session: sessionReducer
};
const reducer = combineReducers(reducers);
- Initiate the session service:
import { createStore } from 'redux';
import { sessionService } from 'redux-react-session';
const store = createStore(reducer)
sessionService.initSessionService(store);
The examples simulates a simple login/logout that sends requests to a server.
- get into the folder:
cd examples/example
- install dependencies:
npm install
- run the example:
npm start
- get into the folder:
cd examples/react-router-v4-example
- install dependencies:
npm install
- run the example:
npm start
Initialize an instance of the session service.
The promise will be resolved if the session is valid, and will be rejected if there is no data in the storage.
Once the promise is resolved or rejected the flag checked
in the redux store will change from false
to true
. This allows to check into any component if the session was already checked and it's valid.
Options:
- refreshOnCheckAuth(default: false): Refresh Redux store in the
checkAuth
function - redirectPath(default:
"login"
): Path used when a session is rejected or doesn't exist - driver: Force to use a particular driver, could be: 'INDEXEDDB', 'WEBSQL', 'LOCALSTORAGE' or 'COOKIES'
- validateSession: Function to validate the saved session. It can either be a function to return an immediate boolean value or a function that returns a promise. In the case it returns an immadiate value and
false
is returned the session will be destroyed. In the case of a promise, if eitherfalse
is returned or an exception is thrown, the session will be destroyed. Example:
const validateSession = (session) => {
// check if your session is still valid
return true;
}
const options = { refreshOnCheckAuth: true, redirectPath: '/home', driver: 'COOKIES', validateSession };
sessionService.initSessionService(store, options)
.then(() => console.log('Redux React Session is ready and a session was refreshed from your storage'))
.catch(() => console.log('Redux React Session is ready and there is no session in your storage'));
const validateSession = (session) => {
// check if your session is still valid with a server check, through axios for instance
return api.invokeRemoteSessionValidationThroughAxios(session).then(response => response.isSessionValid);
}
const options = { refreshOnCheckAuth: true, redirectPath: '/home', driver: 'COOKIES', validateSession };
sessionService.initSessionService(store, options)
.then(() => console.log('Redux React Session is ready and a session was refreshed from your storage'))
.catch(() => console.log('Redux React Session is ready and there is no session in your storage'));
Force to refresh the Redux Store from the local storage.
The promise will be resolved if the session is valid, and will be rejected if there is no data in the storage.
Note: this function is called once the session service is initialized
Authorization function for react-router to restrict routes, it checks if exist a session and redirects to the redirectPath
Example:
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import { sessionService } from 'redux-react-session';
import App from './components/App';
import HomePage from './containers/HomePage';
import LoginPage from './containers/LoginPage';
export default (
<Route path="/" component={App}>
<IndexRoute onEnter={sessionService.checkAuth} component={HomePage} />
<Route path="login" component={LoginPage} />
</Route>
);
Note: If you're using react-router v4 this function it's not necessary. Check out the react-router-v4-example
Note: This function could be used in the client side as well as the server side.
Saves the session object in the storage/cookies and changes the authenticated
flag to true
in Redux Store
Returns the current session if exists
Example:
loadSession
.then(currentSession => console.log(currentSession))
.catch(err => console.log(err))
Deletes the current session from the storage/cookies
Saves the user object in the storage/cookies and in the Redux Store
Returns the current user if exists
Deletes the current user from the storage/cookies
Usage of redux-react-session
with an immutable store is really simple.
Instead of the sessionReducer
import the sessionImmutableReducer
, as the following example:
- Add the session reducer:
import { combineReducers } from 'redux';
import { sessionImmutableReducer as session } from 'redux-react-session';
const reducers = {
// ... your other reducers here ...
session
};
const reducer = combineReducers(reducers);
redux-react-session
also provides methods to keep the session with server rendering using cookies. So the session will work on the server side as well as the client side.
Here is an example using server rendering
Initialize an instance of the server session service.
This function is used in the server.js
to initialize a session service instance in each request.
// server.js
import { sessionService, sessionReducer } from 'redux-react-session';
import { combineReducers, createStore } from 'redux';
// ...
app.use((req, res) => {
const reducer = combineReducers({
session: sessionReducer
});
// Create a new Redux store instance
const store = createStore(reducer);
sessionService.initServerSession(store, req);
// ...
}
// ...
Initialize an instance of the client session service, IMPORTANT to set the option 'COOKIES'(this is the way that the client send the session data to the server).
This function is used in the client.js
of the server rendering to initialize a session service instance.
// client.js
import { createStore } from 'redux';
import { sessionService } from 'redux-react-session';
const store = createStore(reducer)
initSessionService(store, { driver: 'COOKIES' });