Skip to content

Instantly share code, notes, and snippets.

@terrysahaidak
Created September 24, 2018 21:32
Show Gist options
  • Save terrysahaidak/43f316d278f8519538e69e7fd2c737a3 to your computer and use it in GitHub Desktop.
Save terrysahaidak/43f316d278f8519538e69e7fd2c737a3 to your computer and use it in GitHub Desktop.
Mobx-state-tree persist
import { applySnapshot, onSnapshot } from 'mobx-state-tree';
import { transaction } from 'mobx';
import { AsyncStorage } from 'react-native';
const getSnapshots = (storesList, storage) => {
const promises = storesList.map(storeName =>
storage.getItem(storeName),
);
return Promise.all(promises).then(snapshots =>
snapshots.reduce((acc, current, index) => {
const storeName = storesList[index];
acc[storeName] = JSON.parse(current);
return acc;
}, {}),
);
};
const removeSnapshots = (storesList, storage) => {
const promises = storesList.map(storeName =>
storage.removeItem(storeName),
);
return Promise.all(promises);
};
const rehydrateOrApplySnapshot = (store, snapshot) => {
if (!snapshot) return;
if (typeof store.rehydrate === 'function') {
store.rehydrate(snapshot);
} else {
applySnapshot(store, snapshot);
}
};
const purgeStore = ([, store]) => {
if (typeof store.purge === 'function') {
store.purge();
} else {
applySnapshot(store, {});
}
};
const attachSnapshotListeners = (stores, storage) => {
stores.forEach(([name, store]) =>
onSnapshot(store, snapshot =>
storage.setItem(name, JSON.stringify(snapshot)),
),
);
};
const createRehydrate = (storeEntries, storage) => () => {
const storesList = storeEntries.map(i => i[0]);
getSnapshots(storesList, storage).then(snapshots =>
transaction(() =>
storeEntries.forEach(([name, store]) => {
const snapshot = snapshots[name];
rehydrateOrApplySnapshot(store, snapshot);
}),
),
);
};
const createPurge = (storeEntries, storage) => () => {
const storesList = storeEntries.map(i => i[0]);
removeSnapshots(storesList, storage).then(() =>
transaction(() => storeEntries.forEach(purgeStore)),
);
};
const createPersist = (stores, config = {}) => {
let entries = Object.entries(stores);
const storage = config.storage || AsyncStorage;
if (config.whitelist) {
entries = entries.filter(([name]) =>
config.whitelist.includes(name),
);
}
attachSnapshotListeners(entries, storage);
const rehydrate = createRehydrate(entries, storage);
const purge = createPurge(entries, storage);
return {
rehydrate,
purge,
};
};
export default createPersist;
import RootStore from './RootStore';
import createPersist from './persist/createPersist';
const createStores = () => {
const persist = createPersist(RootStore, {
whitelist: ['currentUser', 'ui'],
});
// returns a promise, wait for rehydration if you want to
persist.rehydrate();
// or clean saved data
// persist.purge();
return RootStore;
};
export default createStores;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment