spondbob
spondbob

Reputation: 1633

use middleware to manage localStorage/cookies

On my react-redux app, I have the sign in actions that manage local storage for the token

export function signInUserSuccess(token) {
  localStorage.setItem('token', token);
  return {
    type: SIGNIN_USER_SUCCESS,
    payload: {
      token: token
    }
  }
}

export function signOut() {
  localStorage.removeItem('token');
  return {
    type: SIGNOUT_USER
  }
}

and load any existing token from local storage at index.js

let token = localStorage.getItem('token');
if (token !== null) {
  store.dispatch(signInUserSuccess(token));
}

I know this is not a good approach to have localStorage at actions, and this answer suggests to handle it at middleware.

Having a look at one of the middleware, redux-storage, I do not understand how to replace the localStorage.setItem(), localStorage.removeItem() and localStorage.getItem() with the given middleware operations which only uses LOAD and SAVE actions. I have no problem with setting up the package, but I do not understand how to use it for my sign in and sign out actions.

Upvotes: 1

Views: 1732

Answers (1)

erik-sn
erik-sn

Reputation: 2600

I am not familiar with redux-storage, but I have written simple middlewares for myself to handle this. If you are only doing what is in your example it may be easier to write a small custom middleware rather than add another dependency. For example:

localstorage.js

import { UPDATE_CODE, UPDATE_HISTORY } from '../actions/index';

export default function ({ dispatch }) {
  return next => action => {
    switch (action.type) {
      case UPDATE_CODE:
        localStorage.setItem('code', JSON.stringify(action.payload));
        break;
      case UPDATE_HISTORY:
        localStorage.setItem('history', JSON.stringify(action.payload));
        break;
    }
    next(action);
  };
}

This is in ES6 syntax. Middleware behaves similarly to reducers in that you switch off the action.type. The next is a function that is chained through all your middleware, so you pass the action object to it after you complete your middleware logic.

Then in your root/entry/whatever file (and making sure you accommodate your file structure):

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import LocalStorage from './middlewares/localstorage';

import reducers from './reducers';
import routes from './routes';

const createStoreWithMiddleware = applyMiddleware(LocalStorage)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <Router history={browserHistory} routes={routes} />
  </Provider>
  , document.querySelector('.react-container'));

You can make the middleware logic as complex as you need, or write multiple (one for localstorage, one for cookie?). Actions pass through every middleware.

Upvotes: 1

Related Questions