mobx-state-tree error while converting to anonymousModel

  javascript, mobx, mobx-react, mobx-state-tree, reactjs

What should happen – succesfully create RootStore from defaultSnapshot and reset it when needed, successful backcuping in localStorage.
What happens – getting an error while trying to apply a snapshot, when attempting to open page, just by running code even without interacting with it.

When checking types manually I do not see problems with type mistakes, so can not understand why it throws error.

Codesandox live minimum code

Error

Error: [mobx-state-tree] Error while converting `{"token":"","myInnerInfo":{"login":"","type":""},"myDisplayInfo":{"login":"","type":""},"loginInfo":{"login":"","type":""},"loginList":[],"loading":false,"logined":false}` to `AnonymousModel`:

    at path "/myInnerInfo/login" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).
    at path "/myInnerInfo/type" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).
    at path "/myDisplayInfo/login" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).
    at path "/myDisplayInfo/type" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).
    at path "/loginInfo/login" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).
    at path "/loginInfo/type" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).

File structure

enter image description here

store.js (imported in index.js)

import { types, flow, onSnapshot, applySnapshot } from 'mobx-state-tree';
import { values } from 'mobx';
import axios from 'axios';

const defaultSnapshot = {
  token: '',
  myInnerInfo: { login: '', type: '' },
  myDisplayInfo: { login: '', type: '' },
  loginInfo: { login: '', type: '' },
  loginList: [],
  loading: false,
  logined: false,
}

const User = types
  .model({
    login: '',
    type: '',
  }).actions(self => ({
    setUserInfo({ login, type }) {
      self.login = login;
      self.type = type;
    }
  }))

const RootStore = types
  .model({
    token: '',
    myInnerInfo: types.map(User),
    myDisplayInfo: types.map(User),
    loginInfo: types.map(User),
    loginList: types.array(types.string),
    loading: false,
    logined: false,
  }).views(self => ({
    get loginListLength() {
      return values(self.loginList).length;
    },
  })).actions(self => ({
    // setToken (token) {
    //   self.token = token;
    // },
    // setMyInnerInfo (userInfo) {
    //   self.myInnerInfo.setUserInfo(userInfo);
    // },
    // setMyDisplayInfo (userInfo) {
    //   self.myDisplayInfo.setUserInfo(userInfo);
    // },
    // setLoginInfo (userInfo) {
    //   self.loginInfo.setUserInfo(userInfo);
    // },
    // setLoginList (loginList) {
    //   self.loginList = loginList;
    // },
    // setLoading (loading) {
    //   self.loading = loading;
    // },
    // setLogined (logined) {
    //   self.logined = logined;
    // },
    // reset() {
    //   self.token = '';
    //   self.myInnerInfo = User.create({});
    //   self.myDisplayInfo = User.create({});
    //   self.loginInfo = User.create({});
    //   self.loginList = [];
    //   self.loading = false;
    //   self.logined = false;
    // },
    register: flow(function* register(login, password) {
      self.loading = true;
      try {
        const res = yield axios({
          method: 'POST',
          url: `${process.env.REACT_APP_HOST}/users/register`,
          data: { login, password },
        });
        alert('Registered');
        self.loading=false;
      } catch (e) {
        console.error(e);
        alert(`Error registering! Please retry!`);
        resetStore();
      }
    }),
    login: flow(function* login(login, password) {
      self.loading = true;
      try {
        const res = yield axios({
          method: 'POST',
          url: `${process.env.REACT_APP_HOST}/users/login`,
          data: { login, password },
        });
        self.token = res.data.token;
        self.myInnerInfo.setUserInfo(res.data.user);
        self.myDisplayInfo.setUserInfo({ login: '', type: '' });
        self.loginInfo.setUserInfo({ login: '', type: '' });
        self.loginList = [];
        alert('Logined');
        self.logined = true;
        self.loading=false;
      } catch (e) {
        console.error(e);
        alert(`Error logining! Please retry!`);
        resetStore();
      }
    }),
    unlogin() {
      self.loading = true;
      self.logined = false;
      self.token = '';
      self.myInnerInfo.setUserInfo({ login: '', type: '' });
      self.myDisplayInfo.setUserInfo({ login: '', type: '' });
      self.loginInfo.setUserInfo({ login: '', type: '' });
      self.loginList = [];
      alert('Unlogined');
      self.loading=false;
    },
    getMyInfo: flow(function* getMyInfo() {
      self.loading = true;
      try {
        const res = yield axios({
          method: 'GET',
          url: `${process.env.REACT_APP_HOST}/users/my-info`,
          headers: {'Authorization': self.token ? `Bearer ${self.token}` : ''},
        });
        // self.token = res.data.token;
        // self.myInnerInfo.setUserInfo(res.data.user);
        self.myDisplayInfo.setUserInfo(res.data);
        // self.loginInfo.setUserInfo({});
        // self.loginList = [];
        alert('Loaded information');
        // self.logined = true;
        self.loading=false;
      } catch (e) {
        console.error(e);
        alert(`Error loading information! Please retry!`);
        resetStore();
      }
    }),
    getLoginList: flow(function* getLoginList() {
      self.loading = true;
      try {
        const res = yield axios({
          method: 'GET',
          url: `${process.env.REACT_APP_HOST}/users/list-logins`,
          headers: {'Authorization': self.token ? `Bearer ${self.token}` : ''},
        });
        // self.token = res.data.token;
        // self.myInnerInfo.setUserInfo(res.data.user);
        // self.myDisplayInfo.setUserInfo(res.data);
        // self.loginInfo.setUserInfo({});
        self.loginList = res;
        alert('Loaded list');
        // self.logined = true;
        self.loading=false;
      } catch (e) {
        console.error(e);
        alert(`Error loading list! Please retry!`);
        resetStore();
      }
    }),
    getUserInfo: flow(function* getUserInfo(login) {
      self.loading = true;
      try {
        const res = yield axios({
          method: 'GET',
          url: `${process.env.REACT_APP_HOST}/users/my-info/${login}`,
          headers: {'Authorization': self.token ? `Bearer ${self.token}` : ''},
        });
        // self.token = res.data.token;
        // self.myInnerInfo.setUserInfo(res.data.user);
        // self.myDisplayInfo.setUserInfo(res.data);
        self.loginInfo.setUserInfo(res.data);
        // self.loginList = [];
        alert('Loaded information');
        // self.logined = true;
        self.loading=false;
      } catch (e) {
        console.error(e);
        alert(`Error loading information! Please retry!`);
        resetStore();
      }
    }),
  }));

const store = RootStore.create();

if(!(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] && JSON.parse(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY]))) {
  localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] = JSON.stringify(defaultSnapshot);
}
applySnapshot(store, JSON.parse(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY]));

onSnapshot(store, snapshot => {
  localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] = JSON.stringify(snapshot);
  console.info(snapshot);
});

export default store;
export function resetStore() {
  localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] = JSON.stringify(defaultSnapshot);
  applySnapshot(store, JSON.parse(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY]));
}

package.json

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.9",
    "@testing-library/react": "^11.2.3",
    "@testing-library/user-event": "^12.6.0",
    "axios": "^0.21.1",
    "mobx": "^6.0.4",
    "mobx-react": "^7.0.5",
    "mobx-state-tree": "^5.0.0",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "4.0.1",
    "web-vitals": "^0.2.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Source: Ask Javascript Questions

LEAVE A COMMENT