michaelcontento / redux-storage

Persistence layer for redux with flexible backends
MIT License
675 stars 50 forks source link

Combining engines #126

Closed jetpacmonkey closed 8 years ago

jetpacmonkey commented 8 years ago

I've written a custom engine that I only want to use for a few keys in my state. The rest of them, I'd like to use redux-storage-engine-localstorage for. I assumed from the naming that this is what redux-storage-merger-immutablejs was for, but that doesn't appear to be the case.

My attempted approach:

import filter from 'redux-storage-decorator-filter';
import merge from 'redux-storage-merger-immutablejs';
import localStorageEngine from 'redux-storage-engine-localstorage';

const SPECIAL_FIELDS = [
  ['nested', 'key']
];

export default (key) => merge(
  filter(myEngine, SPECIAL_FIELDS),
  filter(localStorageEngine(key), null, SPECIAL_FIELDS)
);

So what should I be doing here?

jetpacmonkey commented 8 years ago

After a few more minutes of thought, I can pretty easily write an engine (or decorator, or whatever the terminology should be) that does what I expected the merger to do...

const merge = (...engines) => ({
  load() {
    engines.forEach(e => { e.load(); });
  },
  save(state) {
    engines.forEach(e => { e.save(state); });
  }
});
michaelcontento commented 8 years ago

The job of a merger in redux-storage is to merge (hence the name 😄 ) the current state with state loaded from the engine (see https://github.com/michaelcontento/redux-storage/blob/master/src/reducer.js#L8).

Thus a merger would not be the right place to handle multiple engines. The best way would be to create a new engine, as it would be able to handle both load and save operations. A rough API could look something like this:


import createEngineLocalstorage from 'redux-storage-engine-localstorage';
import createEngineRouter from 'redux-storage-engine-router';

const engine = createEngineRouter({
    user: createEngineLocalstorage('userState'),
    todos: createEngineLocalstorage('todosState'),
   __default__: createEngineLocalstorage('defaultState')
});

In this, very very rough, API we simply pass a object to our new router-engine which serves as a routing layer. state.user would be stored in the localStorage key userState, state.todos in todosState and every other property of state in defaultState.

Does this answer your question? If so, please close this issue 😄

michaelcontento commented 8 years ago

I'll go ahead and close this issue now, as it seems to be inactive / solved. Feel free to reopen if this issue still exists!