-
-
Save du5rte/dbd18a1a6dc72d866737a5e95ca1e663 to your computer and use it in GitHub Desktop.
| 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 |
@dizys nice one. Currently, I use mobx-persist-store as it's a library plus battle-tested with edge-cases. Works with TypeScript as well 🎉
Hi there
I'm trying to read read/write in store but from differents browser tabs:
URL for tab1: /mydomain
URL for tab2: /mydomain/test
I'm trying to figure out how to set reaction to listen changes in localstorage. The flow will be like this:
tab1 set var visible in store to true, then tab2 listen the change (from localstorage I suppose) and show something into tab2.
Is it possible to do that? Any idea how to do it?
thanks in advance.
@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 :)
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.
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);
My helper function as a universal solution:
Usage: