Coder Social home page Coder Social logo

mobx-persist's Introduction

Mobx Persist

npm version

$ npm install mobx-persist --save

Usage

import { observable } from 'mobx'
import { create, persist } from 'mobx-persist'

class SomeItem {
    @persist @observable  name = 'some'
    @persist @observable count = 0
}

class SomeStore {
    @persist('object') @observable         obj = { a: 1, b: 2 }
    @persist('map')    @observable   stringMap = observable.map<string>({})
    @persist('list')   @observable     numList = [1,2,3,4]
    @persist('object', SomeItem) @observable s = new SomeItem
    @persist('map', SomeItem)    @observable m = observable.map<SomeItem>({})
    @persist('list', SomeItem)   @observable l = []
}

const hydrate = create({
    storage: localForage,   // or AsyncStorage in react-native.
                            // default: localStorage
    jsonify: false  // if you use AsyncStorage, here shoud be true
                    // default: true
})

// create the state
export const someStore = new SomeStore()
hydrate('some', someStore).then(() => console.log('someStore has been hydrated'))

without decorators

const data = observable({
    title: 'no decorator',
    someObject: {
        a: 1,
        b: 'b',
    },
    someArray: [{
        c: 1,
        d: 'd'
    }]
})
const schema = {
    title: true,
    someObject: {
        type: 'object',
        schema: {
            a: true,
            b: true
        }
    },
    someArray: {
        type: 'list',
        schema: {
            c: true,
            d: true
        }
    }
}
export const someStore = persist(schema)(data)
hydrate('some', someStore).then(() => console.log('someStore has been hydrated'))

with initial state

const initialState = window.__STATE__.some || {
    obj: { a: 2, b: 1 }
}
export const someStore = new SomeStore()

hydrate('some', someStore, initialState)
    .then(() => console.log('some hydrated'))

re-hydration

const result = hydrate('some', someStore, initialState)
const rehydrate = result.rehydrate
result.then(() => console.log('some hydrated'))

setTimeout(() => {
    rehydrate().then(() => console.log('rehydrated'))
}, 3000)

API

persist(schema)(object)

  • arguments
    • schema string/object Describes the type of data you are planning to persist. Not needed for JS primitive types. Options: 'object' | 'list' | 'map' or a structured schema object.
    • observable any The observable that you are persisting.
  • returns a persistence-enabled version of observable

create(config)

  • arguments
    • config object Describes the storage container you want your data to reside in.
      • storage localForage/AsyncStorage/localStorage localForage-style storage API. localStorage for Web (default), AsyncStorage for React Native
      • jsonify bool Enables serialization as JSON
      • debounce number Debounce interval applied to storage calls (in miliseconds, default 0).
  • returns
    • hydrate function hydrate(key, store, initialState?, customArgs?)
      • key string The key of your datastore that you want to hydrate from your persisted record.
      • store object The store in which that key resides.
      • initialState object Optional initial state the store is seeded with.
      • customArgs object Optional custom arguments that are available during the deserialization process which can be used to pass in e.g. stores to model constructors during deserialization. See https://github.com/mobxjs/serializr#6-use-custom-arguments-to-inject-stores-to-models
      • returns IHydrateResult

interface IHydrateResult

extends Promise

  • methods
    • rehydrate function
      • returns IHydrateResult

Examples

Dependency

mobx-persist's People

Contributors

barcoo-hb avatar d10221 avatar fiberjw avatar pinqy520 avatar schumannd avatar yogurt1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mobx-persist's Issues

Fails when using a subclassed Store

I am using some shared methods across stores so inherit from a ParentStore class. In this case mobx-persist (or rather serializr) doesnt seem able to deduct the schema correctly.
Minimally adjusted test case from the readme:

import { observable } from 'mobx';
import { create, persist } from 'mobx-persist';


class ParentStore {
}


class SomeStore extends ParentStore {
	@persist('object') @observable         obj = { a: 1, b: 2 };
}

export const someStore = new SomeStore();

const hydrate = create({ jsonify: true });
hydrate('some', someStore, {
	obj: { a: 2, b: 1 } // initial state
}).then(() => console.log('some hydrated')); // post hydration

this gives mobx.module.js?eae6:3100 [mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@2] Error: [serializr] Failed to find default schema for [object Object] which is thrown from serializr

Data only persists first restart

Hi!
Im pretty new to MobX so im struggling a bit.
On my store I persist the data this way:

import { observable, action } from 'mobx'
import { persist } from 'mobx-persist'

class Store {
  @persist('list') @observable eventos = []

  @action addEvento (id, title) {
    this.eventos.push({
      id: id,
      nome: title
    })
  }
}

export default new Store();

then, on my component I have this:
(not sure if this part is right...)

const hydrate = create({ storage: AsyncStorage })
hydrate('list', Store)

Everytime I add an item to my list, it runs this: this.props.store.addEvento(id, title)
The item show correctly, and when I try to restart the first time, it's still there, but on the second time it disappears.

A little video showing the problem:
https://vid.me/nnmqr

know when stores hydrated

Hello,
First, i would like to tell you, the mobx-persist library rocks :-)
I have following case, where i have a store that has a persisted list.
i also have a reaction that listens to changes of the lengt of the array.
Everything works as expected, except when i reload the page, the reaction also triggers the reaction. Is there a way to detect if the store has been hydrated or not?

Regards
Pascal

export default class TestStore {
  @persist("list")
  @observable
  tests = [];

constructor() {

    reaction(
      () => this.tests.length,
      length => {
        if (length > 0) {
          console.log('the array is empty')
        } else {
          console.log('the array has items')
        }
      }
    );

Ability to react to persisted stores being loaded

Hey,

I'm not quite sure if this already possible, so please let me know if I'm wrong. I have a use-case where I have dependent components that I would like to render based on computed values; computed values which are populated by persisted observables.

When I load up the store, at first the observables are unset and so the computed value returns a different value to what it would after the store's persisted state has been loaded. Unfortunately in my component lifecycle I'm not given the ability to react to the computed value.

How would you recommend I solve this use-case? (For the meantime I have dummy calls to the observable values which triggers a componentWillReact, however this is not-desirable!)

Does not work 1

`import { observable, action } from 'mobx';
import { create, persist } from 'mobx-persist';

const DEFAULT_ZOOM = 5;
class Map {
@persist
@observable
zoom = DEFAULT_ZOOM;
}

class UI {
@observable hydrated = false;
@observable map = new Map();
}

const ui = new UI();

const hydrate = create({});

export default ui;
hydrate('map2ui', ui)
`

causes
mobx.module.js?daf9:3516 [mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@1] Error: [serializr] Failed to find default schema for undefined at invariant (serializr.js?967d:44) at Object.serialize (serializr.js?967d:363) at mobx_1.reaction.delay (index.js?b78b:47) at eval (mobx.module.js?daf9:600) at trackDerivedFunction (mobx.module.js?daf9:3287) at Reaction.track (mobx.module.js?daf9:3491) at reactionRunner (mobx.module.js?daf9:599) at Reaction.eval [as onInvalidate] (mobx.module.js?daf9:587) at Reaction.runReaction (mobx.module.js?daf9:3463) at runReactionsHelper (mobx.module.js?daf9:3589)

Allow undefined schema objects

@persist('object', Date) @observable date = undefined or
@persist('object', Date) @observable date

mobx.module.js:3003 [mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@1] Error: [serializr] expected modelSchema, got undefined
    at invariant (serializr.js:28)
    at Object.serializer (serializr.js:880)
    at serializr.js:430
    at Array.forEach (<anonymous>)
    at serializeWithSchema (serializr.js:419)
    at Object.serialize (serializr.js:406)
    at index.js:41
    at mobx.module.js:1266
    at trackDerivedFunction (mobx.module.js:2811)
    at Reaction.track (mobx.module.js:2979)
mobx.module.js:3003 [mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@1] Error: [serializr] expected modelSchema, got null
    at invariant (serializr.js:28)
    at Object.serializer (serializr.js:880)
    at serializr.js:430
    at Array.forEach (<anonymous>)
    at serializeWithSchema (serializr.js:419)
    at Object.serialize (serializr.js:406)
    at index.js:41
    at mobx.module.js:1266
    at trackDerivedFunction (mobx.module.js:2811)
    at Reaction.track (mobx.module.js:2979)

Error when @persist("list") is null

Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@148] Error: [serializr] expected array (like) object

This happens if a property defined as @persist('list', MyClass) @observable myProperty refers to a null value. What is the correct way to serialize when there is a possibility that an array like property may be null?

Migrating persisted variable from type A to type B

Say I have a

@observable
@persist('list')
activities = [];

That we need to change to

@observable
@persist('map')
activities = new Map();

At the moment this change fails for users who are updating the app, since they are trying to hydrate the existing store with activities as a list.

I'm wondering whats the suggested way of handling these types of migrations?

could not persist the object

"reat-native": "0.49.3"
"react": "16.0.0-beta.5"
"mobx": "^3.3.1",
"mobx-persist": "^0.3.4"
"mobx-react": "^4.3.3"
import {observable} from "mobx";
import {persist} from "mobx-persist";

export default class UserModel {
    @persist @observable
    userID = 0;

    @persist @observable
    username = "";

    @persist @observable
    user = "";

    @persist @observable
    hasLogin = false;
}

const persistStore = create({
    storage: AsyncStorage // default localStorage
});
let user = persistStore('user', new UserModel);
user['hasLogin'] = true

it has not persist the object. I get the user object by reload the app, but just get undefined. I need some help.

usage with react can cause race conditions with computed properties derived from persisted value

here is how i had to solve it, by not mounting the app until store was hydrate.

import App from './App';
import store from './Store';//herre is where persist is imported and applied as necessary.
import { create } from 'mobx-persist';
const storeName='foobar';

create()(storeName,store).then(()=>{
    ReactDOM.render(
        <App store={store} />
        , document.getElementById('root'));    
    setTimeout(()=>registerServiceWorker)
});

this is dangerous because computed properties don't cause rerenders in mobx. if this is a bug in mobx instead, feel free to notify them.

Way to trigger autorun even though there's no record in the localstorage

I want to make sure the section value is fetched from the localstorage before running the fetchUserSession(). The problem is that the autorun won't be triggered if there's no record for section in the localstorage, Do you have any way to trigger the autorun even though there's no record in the localstorage?

 class Store{
   @persist @observable private section:string = "something";
    constructor(data: any) {
        autorun(() => (this.section), () => {
                this.fetchUserSession();
        });
    }
}

Post-hydration callback?

Hi!
I'm currently setting a randomly generated userId upon creation of my UserStore.

I would like to @persist this userId and only have it be generated if the variable is empty in the store.
If I set this creation in the constructor of my store it is run every time, only to then be replaced by the persisted id.

I'd rather skip regenerating this Id if I already have done so and persisted it.

Is there a persistLoaded callback or something that gets called on my store after persist is complete that I can use to perform validations post-hydration?

ReferenceError: window is not defined

When using mobx-persist with SSR, I have these messages (printed like 10 times) both in dev or in production mode:

ReferenceError: window is not defined
at /home/www/my-project/node_modules/mobx-persist/lib/storage.js:18:45

How can I suppress them? Should window and localstorage be polyfilled?

Support for sessionStorage

mobx-persist right now supports only localStorage, localForage and AsyncStorage. It would be better if it can support sessionStorage.
hydrate = create({ storage: sessionStorage }).then(() => /*do something*/ );
This will not work as create returns null.

Changes on objects within array are not saved

Hey,
I'm having a persist array like this:

@persist('list') @observable failedUploads = [];

In some of my functions, I'm changing the values of an object this way:

this.failedUploads[index].fails++;

The changes were made successfully, I can validate it by console log. But after reopening the app, they get not restored. I still get the initial value (in my case 1) of the property "fails".

MobX strict mode

Hello, thanks for your awesome work!

Is there a way to make mobx-persist work with mobx strict mode? When I have it turned on, I get Possible Unhandled Promise Rejection warnings, and the stores are not persisted.

If you guide me I can help with a PR on that, since I really want to use the strict mode. The mobx action uses extras.allowStateChanges function under the hood, I think it can be used to ignore the mobx strict mode.

Uncaught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.

This error happens when someone has this option disabled in Chrome:

screenshot 2018-09-28 09 42 22

I am trying to use a memory storage from local-storage-fallback in the case that people have disabled cookies, etc. but an error is thrown inside mobx-persist when accessing localStorage here: https://github.com/pinqy520/mobx-persist/blob/master/src/index.ts#L41

This is the code I'm using:

const { storage } = require('local-storage-fallback');
const hydrate = create({ storage, jsonify: true });
hydrate('checkout-store', this).then(() => {

});

This is the error thrown:
Uncaught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.

simplify object persistence

it would be nice to have this simplified option for generic object persistence:

@persist @observable layerOptions = {
editInProgress: false,
lightning: { renderer: 'webgl'}
}

a generic seriializer a la JSON.stringify would be able to take care this?

Redundant code in types.ts?

First of all, thank you guys for such a great library. I've been trying to understand how this library works and stumbled in the following piece of code:

function _walk(v: any) {
    if (typeof v === 'object' && v) Object.keys(v).map(k => _walk(v[k]))
    return v
}

I'm trying to understand the use of the line if (typeof v === 'object' && v) Object.keys(v).map(k => _walk(v[k])). Tried removing that line and everything is still working as is 😕

Possible Unhandled Promise Rejection (id: 0): Error: Couldn't read row 0, col 0 from CursorWindow.

Hi I have 3 hydrated store in first run my app works well but after fill and persist some object in my store (an array with 14000 object - near 4 or 5 mb size) and reload app my app crashed with this error:

Hydrate: observable userStore hydrated
Hydrate: observable noteStore hydrated
Possible Unhandled Promise Rejection (id: 0):
Error: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
convertError@http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:60275:24
http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:60266:26
map@[native code]
convertErrors@http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:60265:53
http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:60072:35
__invokeCallback@http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:2435:23
http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:2180:34
__guardSafe@http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:2348:13
invokeCallbackAndReturnFlushedQueue@http://192.168.53.189:8081/index.delta?platform=android&dev=true&minify=false:2179:21
invokeCallbackAndReturnFlushedQueue@[native code]

This is my App.js file:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import Root from './app/router/root';
import userStore from "./app/stores/userStore";
import noteStore from "./app/stores/noteStore";
import detailStore from "./app/stores/detailStore";
import {AsyncStorage} from "react-native";
import {create} from "mobx-persist";
import {observer} from "mobx-react/native";

@observer
export default class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            storeHydratedFetched: false,
        };

        // new hydrate approach (hydrate once when app load)
        const hydrate = create({
            storage: AsyncStorage
        });

        hydrate('userStore', userStore).then(() => {
            console.warn('Hydrate: observable userStore hydrated');
            hydrate('noteStore', noteStore).then(() => {
                console.warn('Hydrate: observable noteStore hydrated');
                hydrate('detailStore', detailStore).then(() => {
                    console.warn('Hydrate: observable detailStore hydrated');
                    this.setState({storeHydratedFetched: true});
                });
            });
        });
    }


    render() {
      const { storeHydratedFetched } = this.state;
      console.warn("storeHydratedFetched: " + storeHydratedFetched);
      if (!storeHydratedFetched) {
          return null;
      }

      return <Root />;
  }
}

In above code console.warn('Hydrate: observable userStore hydrated'); and console.warn('Hydrate: observable noteStore hydrated'); works well every time but console.warn('Hydrate: observable detailStore hydrated'); just works in first run or after app clear cache from android setting and didn't work after add 14000 object to it (detailStore).

I also try to increase Android AsyncStorage size based on this tutorial: https://codedaily.io/tutorials/4/Increase-Android-AsyncStorage-Size-in-React-Native but it's still crashed.

Is it related to mobx-persist package.

hydrate promise is not resolved on Android, but works on iOS

I had been developing testing on iOS and I noticed that the hydrate promise is not resolved on Android. I'm new to RN so it's probably something I'm doing wrong, but the fact that it's working on iOS is puzzling.

My store is like this:

class User { //UserStore
  @observable id = 0;
  @observable loading = false;
  @action setUser(json) {
    this.clearUser();
    this.id = json.user.id;
    this.authToken = json.user.token;
    this.name = json.user.name;
    this.email = json.user.email;
    this.loading = false;
  }

  ...

  ...

  @action clearUser() {
    this.id = 0;
    this.authToken = '';
    this.name = 'N/A';
    this.email = '';
  }

  @persist @observable authToken = ''; 
  @persist @observable name = 'Anonymous'; 
  @observable email = '';

}

And in my starting js file I load it like this:

const hydrate = create({ storage: AsyncStorage });

@observer
class LauchContainer extends Component {
  constructor(props) {
    super(props);
    this.props.token = user.authToken; 
  }

  componentDidMount() {
    console.log('hydrating');
    hydrate('user', user)
      .then(() => {
        console.log(user); 
        if (user.authToken == '') {
          SplashScreen.hide();
          Actions.login();
        } else {
          console.log('we have token, check if it is valid');
          Api.hello().then(() => {
            ...
            }
          });
        }
      }).catch((e) => {
        console.log('hydration failed');
        alert(e);
      });  
}

The above work perfectly on iOS but nothing is logged in Android and nothing runs inside the promise callback.

Am I missing something?

"mobx": "^3.3.1",
"mobx-persist": "^0.4.1",
"mobx-react": "^4.3.4",
"react": "16.0.0",
"react-native": "0.50.1",

Hydration deletes properties on sub-properties added by constructor

I have a stumbled on a problem with nested objects where I pass a value to the child, like so:

  constructor(foo) {
    this.someValue = foo;
  }

After hydrating, the value is no longer there. Here's a reproducible example: https://codesandbox.io/s/qvp7x01x59

In the example I'm creating a store along with a child object created by another class. A value is passed to the child when instantiated, and is accessible directly after the store has been created. However, after being hydrated, it's lost.

Update:
I'm guessing that this has to do with createSimpleSchema and not createModelSchema being used. I would gladly do a PR but I'm having trouble setting up environment and grasping the code since I'm not used to neither xcode nor typescript. It would be neat if the end result would be a third parameter being passed, something like:

@persist('object', Model, params)
@observable
new Model(params)

Could there be some examples that do not use decorators?

Not everywhere supports decorators (i.e. create-react-app or next.js) so to use MobX stores need to be setup/written without decorators.

It hasn't been immediately clear how to use @persist because I'm not sure what some of the types of the TypeScript code are or how the overloading plays out.

Could there be some examples written without decorators?

How works with multiple stores?

Hi! I'm trying to set up multiple stores, but it does not work. I leave the code I'm working with.

import { create } from 'mobx-persist';
import { AsyncStorage } from 'react-native';

import AppStore from './appStore';
import AuthStore from './authStore';
import LocalesStore from './localesStore';

const persistStore = create({ storage: AsyncStorage });

const store = {
  app: new AppStore(),
  auth: new AuthStore(),
  locales: new LocalesStore()
};

export default persistStore('store', store);

Neither works this way

const store = {
  app: persistStore('app', new AppStore()),
  auth: persistStore('auth', new AuthStore()),
  locales: persistStore('locales', new LocalesStore())
};

Any examples for this to work? Thanks in advance.

Array not persist in @observable object

@persist('object') @observable dataObj = {
    employees: [],
    equipments: [],
  }

I have above persist observable object and its properties employees and equipments.
When I push data in employees (eg. employess = [ {}, {} ] )

Now when I reopen app, I can not get employees with data, I got only blank array.

console.log('Employees: ', store.dataObj.employees)

print => []

list not save

Hello,I try to save a array,but it is not work.
Here us the code
Chat.js
// @flow
import { observable, action } from 'mobx';
import { persist } from 'mobx-persist';
// import { ENTRIES } from '../Phone/HomePage/src/static/entries';
class Store {
@persist('list')@observable message=[
{
id:1,
name:'測試1',
chat:[
{
_id: 1,
text: 'Hello developer',
createdAt: new Date(Date.UTC(2016, 5, 11, 17, 20, 0)),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
},
{
_id: 2,
text: 'Hello developer',
createdAt:"2017/12/09",
user: {
_id: 2,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
},
{
_id: 3,
text: '最後的訊息01',
createdAt:"2017/12/09",
user: {
_id: 2,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
}
]},
{
id:2,
name:'測試2',
chat:[
{
_id: 1,
text: 'Hello developer',
createdAt:"2017/12/09",
user: {
_id: 2,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
},
{
_id: 2,
text: 'Hello developer',
createdAt:"2017/12/09",
user: {
_id: 2,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
},
{
_id: 3,
text: '這是最後的訊息喔',
createdAt:"2017/12/09",
user: {
_id: 2,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
}
]}]
@action addMessage(id) {
this.message[0].chat.push({
_id: 5,
text: 'Hello developer',
createdAt:"2017/12/09",
user: {
_id: 6,
name: 'React Native',
avatar: 'https://facebook.github.io/react/img/logo_og.png'
}
});
console.log(this.message[0].chat);
}
}
export default new Store();

index.js

import { create } from 'mobx-persist';
import { AsyncStorage } from 'react-native';
import Login from '../Mobx/Login/Login';
import Chat from '../Mobx/Chat/Chat';
const hydrate = create({ storage: AsyncStorage });

const stores = {
Login,
Chat
};
hydrate('Chat', stores.Chat)
.then(() => console.log('some hydrated'));
export default {
...stores
};

Detecting crashes from restored state

Hi There,

Not sure if this have come up yet but if my app crashes within a short amount of time of running hydrate I'd like to clear all the persistence. Seems like a useful feature for obvious reasons, what do you thing?

Close if you can't help! I'm really impressed with how well this library is working with react-navigation!

Mongodb Driver

Redux has this awesome driver called redux-persist-mongodb-storage right now. I wonder if there is gonna be any way we can have similar for mobx-persist.

Not working when changing object

Hey,
in the first version of our app, we have an object like this defined:

@persist('object') @observable notifications = {
    seenTutorial: false,
};

In a newer version, we have to add a new value to it, f.e.:

@persist('object') @observable notifications = {
    seenTutorial: false,
    seenFolderChoose: false
};

If we know modify seenFolderChose to true, the change won't be saved to the disk and there is also no "re-render" when changing the value (most of the time, sometimes we got one).

Reaction[Reaction@21] Error: [serializr] Failed to find default schema for [object Object]

Hey,
when I try to call hydrate, I get the following error:

 ExceptionsManager.js:71 [mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@21] Error: [serializr] Failed to find default schema for [object Object]

Any idea what could cause this? If I remove hydrate, everything is working fine again.

It even happens if I create a new store:

class Test {
    @observable test = true;

    constructor() {

    }
}

const testStore = new Test();


hydrate('test',testStore).then(() => {


});

What is the point of provide Model class as a second agruement of @persist?

In the example:

class SomeItem {
    @persist @observable  name = 'some'
    @persist @observable count = 0
}

class SomeStore {
    @persist('object') @observable         obj = { a: 1, b: 2 }
    ...
    @persist('object', SomeItem) @observable s = new SomeItem
    ...
}

What is the gain of create SomeItem class then pass it as a Model?
I try to create an empty model class to test and everything is still working :/. Did I miss something?

class Todo {}

class TodoList {
    @persist('list', Todo) @observable todos = [];
    ...
}

Remove store by name

Hi!

I'm using mobx-persist in a react-native project. Is there any way to remove store by key?

Class actions workaround

Hello, can u pls explain, how can i execute actions from my obsevable on a valueView, created from that observable.

How to use with mst ?

Hello,

Is it possible to use mobx-persist with mobx-state-tree ?
If so, can you give an example ?

Thanks you

hydrate() reacts and overwrites data in localstorage before object is rehydrated

Pseudocode

class RootStore(){
    @persist('object', User) @observable myUser = new User() //has no properties yet
}


const hydrate = create({
	storage: localForage,
	jsonify: false,
})

const rootStore = new rootStore()

console.log("1 -- Hydrate user")
hydrate("user", rootStore.user).then(() => {
	console.log("2 -- Hydrated user", rootStore.user)
})

...loadUserDataFromServer()

The issue here is that mobx-persist is persisting the empty user before the correct user data has been rehydrated from localstorage. It overwrites the correct data in localstorage with empty data. After data loads from server it writes the correct data again. It seems a guard is missing to prevent mobx-persist from writing to localstorage before it has loaded the data from localstorage for the first time.

Data didn't hydrate as the defined class schema [React Native]

I've a simplified store code in my RN project as following:

class GatewayStore {

    @persist('list', Gateway) @observable gateways = [];
    @computed get gatewayList() {
        return this.gateways.reverse().slice().map(gateway => gateway.asJson);
    }
}

class Gateway {

    @persist id = '';
    @persist @observable name = '';
    @persist @observable key = '';
    @persist @observable ipAddress = '';
    @persist @observable ipVersion = '';

    @computed get asJson() {
        return {
            id: this.id,
            name: this.name,
            ipAddress: this.ipAddress,
            ipVersion: this.ipVersion
        };
    }
}

The problem is that after the hydration, gateways are populated with objects not instances of Gateway and those computed functions are undefined.

Am I missing any configuration for this sort of use cases?

Hard to understand readme example

I am always in favor of examples. But I wish there was some better naming.
E.g.

What does 'some' in

hydrate('some', someStore)

mean or do? In the documentation it is referred to as The key of your datastore. But where is this key initially set?

I thought I understood this package until stuff started breaking and I'm starting over again. If someone explains the usage of @persist and hydrate() I'll rewrite the readme to be more understandable.

Edit:

If I understand correctly, the example is broken and hydrate('some', someStore) does not hydrate anything as there is no datastore key with that name. I will open a PR that fixes this

Mobx state persistance between routes

Hi, I supose it is not the place to post this question but I need a quick answer.
Mobx state can persist between routes changing with mobx-state-router ?
That's mostly what I'm looking for
Thank's

Example for list (array)

I am unable to get the serialization/de-serialization to work with list in react-native asyncStorage, can someone provide example how to do this? I was able to make it work with objects, maps and primitives but never with list (array).

I declare list inside a class
@persist('list') @observable @serializable numList = [1,2,3,4]

and an action to get it

@action getNumList(){console.log(this.numList)}

but the result from the console.log is always empty object.

Also if I do an empty list and than call the setter action to push values inside the array nothing happens and I have again empty object.

Q on state rehydrate

Need some help with my use case.
Using persist I hydrate the org details in local-storage and and rehydrate them. From componentDidMount I make an asyncAction call using the org details. When I refresh first the page org details are empty. ComponentDidMount gets called first before rehydration hence the api calls didn’t make through. How could I over come this? Is there any best practice on when to re hydrate the state on page refresh?

Latest change to state is not persisted

This is a definition inside my store:

@persist('list') @observable formationMatrix: Array<Array<Player>> = []

This is how I add an object to the formationMatrix:

appState.formationMatrix[player.position][this.targetPositionOrder] = player

Note that both of the arrays are initialized before use.

The latest assignment is not persisted to AsyncStorage. Any directions to ease debugging the issue?

Thank you.

Question - detect when local storage changed

The library assumes a one-way direction for updating local storage. The only time the store updated from local storage is on initial load. is there a way to detect that local storage updated and automatically load the new values from there?

to clarify - assume some code updates localstorage outside of the store, i need a way to send an event to the store asking to reload changes from localstorage.

it dosent work on RN

I write the same code for RN, but it dosent work, I cant find any state under window__STATE__, how can I initail the state that I have persisted

How to persist structured objects

I have an observable range object that I want to persist. It is defined as follow:

range = {
    start: moment(),
    end: moment()
}

where start and end are moment.js objects.

With plain serializr I would do something like

const rangeSerializer = ({start, end}) => {
	return {start: start.unix(), end: end.unix()}
}

const rangeDeserializer = ({start, end}) => {
	return {start: moment.unix(start), end: moment.unix(end)}
}

class Store {
    @serializable(custom(rangeSerializer, rangeDeserializer)) @observable range = {}
}

but using @persist(custom(rangeSerializer, rangeDeserializer)) @observable range = {} does not work. I get no erros but data are never written to localStorage. When instead I remove that persist the other persisted data contained in Store are correctly written to localStorage.

Encrypting data - best practice?

I'd like my data to be encrypted when persisted. What would you suggest as a best practice for that? suppose I'll take care of the encrypting key generation and the algorithm - where would be the best place to perform such an action in the flow? My case is in React Native.

Problem with React Native

Hello, thanks a lot for your library 🙌
I'm developing app with RN + MobX (+ your persist library) and have faced a problem when I wanted to create @persist('map', SomeItem) with Models.User which I defined as in your example in README. Everything seemed to be working good but I was getting an error when I tried to hydrate my multiple stores. After some research, I have solved it by changing @persist('map', SomeItem) @observable m = asMap<SomeItem>({}) to @persist('map', Models.User) @observable users = observable.map({});. I will put some code here if someone has the same problem in future.

stores/index.js:

import { create } from 'mobx-persist';
import { AsyncStorage } from 'react-native';

import Account from './Account';
import Profiles from './Profiles';

const hydrate = create({ storage: AsyncStorage });

const store = {
  Account,
  Profiles,
}

hydrate('Account', store.Account);
hydrate('Profiles', store.Profiles);

export default {
  Account,
  Profiles,
};

stores/Profiles.js:

import { observable, action, computed } from 'mobx';
import { persist } from 'mobx-persist';

import Models from '../Models/index';

class Store {
  @persist('map', Models.User) @observable users = observable.map({});

  // some methods and props...

}

export default new Store();

Models/User.js:

import { observable } from 'mobx';
import { persist } from 'mobx-persist';

class User {
  @persist @observable id = 0
  @persist @observable first_name = ''
  @persist @observable last_name = ''

  // more properties
}

export default User;

This code works for me in RN. Maybe you could add this example to the README, I think it would be helpful for others.

More documentation please

Hi,

This repo looks promising but it would be nice if we have more documentation or more sample.

I am looking at this sample https://github.com/pinqy520/mobx-persist/tree/master/examples/rn/src but I don't see how rehydration works.

What are we supposed to do in in those hydrated methods?

console.log('some hydrated')

What I am trying to is to save the data in local storage or session storage and get the data back on page refresh.

I created this sample to show you what I am trying to do. https://github.com/michaelsync/js-lab/tree/master/mobx-persist-sample .

You can use the following command to run the sample.

  • yarn install
  • yarn start

It has two components called "entry" page and "result". User can enter something in "entry" page and show that data in the "result" page. There is one store called userDataStore that has only one property called data.

When you click on "Click Me" in the entry page, the data that you typed on text box will be saved in user data store. and it retrieves the data back from the result page.

The steps to replicate the issue.

  1. run the program by using yarn start
  2. enter something in textbox and click on "Click me" (It will redirect to the result page)
  3. you will see what you entered in the result page.
  4. Refresh the page (press F5) - the data will be lost.

The issue is that I don't know what to do in rehydration. I am using the provider to inject the store.

Can you please help me with the steps that I need to do in hydration and rehydration?

Updated

The solution that I found is to use the sessionStorage/local storage directly from store instead of using mobx-persit. but yes. I still would like to know if there is any better way. Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.