Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
One way to create a local storage solution with Pullstate
import { Store } from "pullstate";
import { LocalStorage } from "@gt/gt-frontend/build/localStorage/LocalStorage";
import { get, pick, set } from "lodash";
interface IStoreWithValues<S> {
key: string;
store: Store<S>;
values?: Array<keyof S>;
deepValues?: string[];
}
export class StoreLocalStorage {
storesWithValues: Required<IStoreWithValues<any>>[] = [];
namespace: string;
constructor(namespace: string = "store-local-storage") {
this.namespace = namespace;
}
addStore<S>({ key, store, values = [], deepValues = [] }: IStoreWithValues<S>) {
this.storesWithValues.push({
key,
store,
values,
deepValues,
});
}
async initiateLocalStorageValues() {
for (const SV of this.storesWithValues) {
const localStorageValue = await LocalStorage.get(`${this.namespace}_${SV.key}`);
const foundLocal = JSON.parse(localStorageValue != null ? localStorageValue : "{}");
let foundDeepValues: any = {};
if (SV.deepValues.length > 0) {
const localStorageDeepValue = await LocalStorage.get(`${this.namespace}_${SV.key}_deep`);
foundDeepValues = JSON.parse(localStorageDeepValue != null ? localStorageDeepValue : "{}");
}
SV.store.update(s => {
for (const [key, value] of Object.entries(foundLocal)) {
s[key] = value;
}
for (const deepValPath of SV.deepValues) {
if (foundDeepValues.hasOwnProperty(deepValPath)) {
set(s, deepValPath, foundDeepValues[deepValPath]);
}
}
});
SV.store.subscribe(
s => pick(s, SV.values),
keepLocal => {
LocalStorage.set(`${this.namespace}_${SV.key}`, JSON.stringify(keepLocal));
}
);
if (SV.deepValues.length > 0) {
SV.store.subscribe(
s => {
const resp: any = {};
for (const deepValPath of SV.deepValues) {
resp[deepValPath] = get(s, deepValPath);
}
return resp;
},
keepLocal => {
LocalStorage.set(`${this.namespace}_${SV.key}_deep`, JSON.stringify(keepLocal));
}
);
}
}
}
}
@lostpebble
Copy link
Author

lostpebble commented Aug 20, 2019

Usage is like so:

export const LocalStorageCore = new StoreLocalStorage();

LocalStorageCore.addStore({ key: "ui-store", store: UIStore, deepValues: ["theme.dark"] });
LocalStorageCore.addStore({
  key: "gis-store",
  store: GISStore,
  deepValues: [
    "map.center",
    "map.zoom",
    "userSelectedSubType",
    "userSelectedGeoLvlType",
    "queryOptions.subType",
    "queryOptions.geoLvlType",
    "queryOptions.searchText",
    "tileLayerChoice",
    "tileLayerTemplate",
  ],
});

@lostpebble
Copy link
Author

lostpebble commented Aug 20, 2019

And then you need to wait for it to pull the values from local storage before doing the first render:

LocalStorageCore.initiateLocalStorageValues().finally(() => {
    ReactDOM.render(
      <PullstateProvider instance={instance}>
         <App />
      </PullstateProvider>,
      document.getElementById("react-mount")
    );
  });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment