Skip to content

Instantly share code, notes, and snippets.

@du5rte
Last active August 30, 2024 18:08
Show Gist options
  • Save du5rte/dbd18a1a6dc72d866737a5e95ca1e663 to your computer and use it in GitHub Desktop.
Save du5rte/dbd18a1a6dc72d866737a5e95ca1e663 to your computer and use it in GitHub Desktop.
Auto saving to localStorage with MobX
import mobx from "mobx"
import store from "store"
export default function(_this) {
let firstRun = true
// will run on change
mobx.autorun(() => {
// on load check if there's an existing store on localStorage and extend the store
if (firstRun) {
const existingStore = store.get("store")
if (existingStore) {
mobx.extendObservable(_this, existingStore)
}
}
// from then on serialize and save to localStorage
store.set("store", mobx.toJS(_this))
})
firstRun = false
}
import mobx, { computed, observable } from "mobx"
import autoSave from "./autoSave"
const initialTodoStore = {
todos: ["buy milk", "buy eggs"]
}
class TodoStore {
constructor() {
// set initial mock up examples
this.todos = initialTodoStore // or []
// in the future it will over run it and save to store
autoSave(this)
}
@observable todos
@observable filter = ""
@computed get filteredTodos() {
const filter = new RegExp(this.filter, "i")
return this.todos.filter(todo => !this.filter || filter.test(todo))
}
}
const todoStore = window.todoStore = new TodoStore
export default todoStore
@deadcoder0904
Copy link

@hartum websockets maybe? idk why you wanna persist such data in localstorage but i guess hmr in react/next works like that only. they use websockets to listen if ui in one browser changed & update it everywhere i guess :)

@hartum
Copy link

hartum commented Nov 2, 2021

Using websockets seems to me a bit drastic solution. The reason is two browser windows/tabs of the same SPA, because the client wants to open several instances of components and be able to use it on several monitors.

@hartum
Copy link

hartum commented Nov 8, 2021

In case anyone is interested what I did to solve my problem was to use the 'mobx-persist-store' library to write my store data to the localStorage.
Then (inside my store) I added a store event listener and update it every time I detect a change.

in mobxStore.ts

import { makePersistable, hydrateStore } from 'mobx-persist-store';

class Store {
  // --- STORE STATE VARS ---
  dashboard = {
    isVisible: true,
  };

  constructor() {
    makePersistable(this, { name: 'mobxStore',
      properties: ['dashboard'],
      storage: window.localStorage }).finally(() => {});
   }

  // --- SHOW/HIDE DASHBOARD ---
  setDashboard(visible: boolean) {
    this.dashboard.isVisible = visible;
  }
}

const myStore = new Store();

window.addEventListener('storage', (e) => {
  if (e.key === 'mobxStore') {
    myStore.hydrateStore().catch(() => {});
  }
});

export default myStore;

in a different window (but same domain http://localhost:3000/test )the component:

import React from 'react';

import { observer } from 'mobx-react';
import store from 'store/mobxStore';

const FakeComponent = () => {
  const visible = store.dashboard.isVisible;
  return (
    <div>
      {store.dashboard.isVisible ? <span>Dashboard visible</span> : <span>Dashboard Invisible</span>}
      <br />
      <div onClick={() => store.setDashboard(!visible)} >"Switch dashboard visibility"</div>
    </div>
  );
};

export default observer(FakeComponent);

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