mst-persistent-store

Mobx State Tree Persistant Store Provider Component and Consumer Hook writen in TypeScript

Usage no npm install needed!

<script type="module">
  import mstPersistentStore from 'https://cdn.skypack.dev/mst-persistent-store';
</script>

README

Mobx State Tree Persistent Store

Star IT Ltd

A factory to easily create Persistent Mobx State Tree Store Provider and consumer hook.

Installation

yarn add mst-persistent-store

Install the peerDependencies if you haven't already.

For React

yarn add mobx-state-tree localforage

For React Native

yarn add mobx-state-tree @react-native-async-storage/async-storage

Usage

Usage is very simple.

Create Provider and Hooks

Below is an example on how to create the provider and consumer hook.

// store-setup.ts
import { types } from 'mobx-state-tree';
import createPersistentStore from 'mst-persistent-store';

const PersistentStore = types
  .model('RootStore', {
    name: types.string,
    age: types.number,
    premium: types.boolean,
    hydrated: types.boolean,
  })
  .actions((self) => ({
    hydrate() {
      self.hydrated = true;
    },
  }))
  .views((self) => ({
    get isAdult() {
      return self.age >= 18;
    },
  }));

export const [PersistentStoreProvider, usePersistentStore] = createPersistentStore(
  PersistentStore,
  {
    name: 'Test User',
    age: 19,
    premium: false,
    hydrated: false,
  },
  {
    hydrated: false,
  },
  {
    logging: false,
    devtool: false,
  }
);

Add Provider to The Root Component

Wrap your app with the created Provider component.

// app.tsx
import { PersistentStoreProvider } from './store-setup';
import Main from './main';

export default function App() {
  return (
    <PersistentStoreProvider>
      <Main />
    </PersistentStoreProvider>
  );
}

Use the Store from Child Components

Consume store values using the hook.

// main.tsx
import { observer } from 'mobx-react-lite';
import { useEffect } from 'react';
import { usePersistentStore } from './store-setup';

const Main = observer(() => {
  const { name, age, isAdult, hydrated, hydrate } = usePersistentStore();

  useEffect(() => {
    hydrate();
  }, []);

  if (!hydrated) {
    return <p>Loading...</p>;
  }

  return (
    <div>
      <p>
        {name} is {age} years old and {isAdult ? 'is' : 'is not'} an adult.
      </p>
    </div>
  );
});

export default Main;

API

createPersistentStore

Type Definition

interface PersistentStoreOptions {
  storageKey: string;
  writeDelay: number;
  logging: boolean;
  devtool: boolean;
}
const createPersistentStore: <T extends IAnyModelType>(
  store: T,
  init: SnapshotIn<T>,
  blacklist?: PartialDeep<SnapshotIn<T>> | undefined,
  options?: Partial<PersistentStoreOptions> | undefined
) => readonly [React.FC<{}>, () => Instance<T>];

Arguments

param type required description
store T extends IAnyModelType yes the mst model to instantiate
init SnapshotIn yes the init data of the store
blacklist PartialDeep<SnapshotIn> no the part of the store that should not be persisted
options Partial no Various options to change store behavior

PersistentStoreOptions

All Properties are optional.

property type default description
storageKey string persistentStore the key to use as the localforage key. Must be
changed when using multiple stores in the same
app to avoid overriding data.
writeDelay number 1500 On Repeated Store Update, it's advisable to wait
a certain time before updating the persistent
storage with new snapshot. This value controls the
debounce delay.
logging boolean true is dev
false in prod
Whether to enable logging.
devtool boolean true in dev
false in prod
Whether to integrate with mobx-devtool

License

This package is licensed under the MIT License.

Contribution

Any kind of contribution is welcome. Thanks!