aohua/redux-state-sync

[Issue] Prevent writing `LAST_ACTION` to localStorage unless predicate is true.

Closed this issue · 3 comments

On the codebase that I am working on, we are dealing with very large state objects that exceed the amount allowed by localStorage. We had to override actionStorageMiddleware with our own version that prevented localStorage.setItem('LAST_ACTION', .. from happening unless action.type was allowed. So my question is, does every action have to be stored even if you're only allowing a few of them? Let me know if this tweak falls within the purpose of redux-state-sync and we can continue this conversation.

aohua commented

I think it's not necessary to store those actions which are not allowed. Do you want to send a pull request with the tweak that you did?

We have some syntactic sugar(wrapper) around the framework, so we made the change in our codebase. We overwrote the middleware portion of your framework. From what I'm seeing, it may require a few changes to the API, I could be mistaken though. Could you checkout my code snippet below and fiddle around with some ideas on how you would like to accomplish this?

// TabSyncMiddleware.js
import { createStorageListener, withReduxStateSync } from 'redux-state-sync';
import ActionWhiteList from './ActionWhiteList'; // actions we want to sync across tabs

function s4() {
  return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}

function guid() {
  return `${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}-${s4()}`;
}

export const reducerTabSync = withReduxStateSync;

export const tabSyncMiddleware = ({ getState }) => (next) => (action) => {
  if (action && !action.$uuid) {
    const stampedAction = {
      $uuid: guid(),
      ...action
    };

    try {
      if (action.type === '&_SEND_INIT_STATE') {
        if (getState()) {
          stampedAction.payload = getState();
          localStorage.setItem('LAST_ACTION', JSON.stringify(stampedAction));
        }
        return next(action);
      }

      if (ActionWhiteList.includes(action.type)) { // here's the part we needed
        localStorage.setItem('LAST_ACTION', JSON.stringify(stampedAction));
      }
    } catch (e) {
      console.error('Failed to store `LAST_ACTION` to localStorage.');
    }
  }
  return next(action);
};

export const TabSyncWrapper = (store) => {
  createStorageListener(store, {
    initiateWithState: true,
    predicate: (actionType) => {
      return ActionWhiteList.includes(actionType);
    }
  });

  return store;
};

Usage

//  index.js
import { tabSyncMiddleware, TabSyncWrapper, reducerTabSync } from './middleware/TabSyncMiddleware';

// ...


const enhancer = composeEnhancers(
  applyMiddleware( ..., ..., tabSyncMiddleware)
);

const store = TabSyncWrapper(createStore(
  reducerTabSync(reducers),
  enhancer
));

// ...

render(
  <Provider store={store}>
    <AppRouter />
  </Provider>,
  document.getElementById('root')
);
aohua commented

Sorry for the long delay, I just released redux-state-sync 2.0, Your problem should be fixed in the new version.