parket

by ForsakenHarmony

ForsakenHarmony / parket

A library to manage application state, heavily inspired by mobx-state-tree

429 Stars 15 Forks Last release: over 2 years ago (0.4.2) 73 Commits 17 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:



  • Small (~1.5KB)
  • Immutable from the outside, mutable in actions
  • Reactive (state emits updates without explicit calls to i.e.
    setState
    )
  • Modular (you can nest models inside each other)

Why?

I was disappointed with all the current state management solutions. Then I found mobx-state-tree, which seemed like a godsend to me (ok not really, but I liked the concept), but it was pretty big in terms of file size (mobx alone is big: 16.5kB). So I thought it's surely possible to make a smaller version of it, that's how this started. And after 2 failed attempts I finally got something that works well

Installation

$ npm i parket
// ES6
import { model } from 'parket';
// CJS
const { model } = require('parket');

Usage

Note: This library uses Proxies and Symbols. Proxies cannot be fully polyfilled so you have to target modern browers which support Proxies.

Basic example

import { model } from 'parket';
// model returns a "constructor" function
const Person = model('Person', {
  // name is used internally for serialization
  initial: () => ({
    firstname: null,
    lastname: null,
    nested: null,
  }),
  actions: (state) => ({
    setFirstName(first) {
      state.firstname = first; // no set state, no returns to merge, it's reactive™
    },
    setLastName(last) {
      state.lastname = last;
    },
    setNested(nested) {
      state.nested = nested;
    },
  }),
  views: (state) => ({
    fullname: () => `${state.firstname} ${state.lastname}`, // views are computed properties
  }),
});

// merge an object with the initial state const instance = Person({ firstname: 'Tom' });

// you can subscribe to actions, patches (state updates) and snapshots (full state after actions) const unsubscribe = instance.onSnapshot(console.log);

// you can unsubscribe by calling the function returned by the listener // unsubscribe();

instance.setLastName('Clancy');

// views turn into cached getters console.log(instance.fullname); // 'Tom Clancy'

// nested models also bubble up events to the parent instance.setNested(Person());

instance.nested.setFirstName('wow');

// you can get a snapshot of the state at any time // { firstname: 'Tom', lastname: 'Clancy', nested: { firstname: 'wow', lastname: null, nested: null } } console.log(instance.getSnapshot());

Async example

const Async = model('Async', {
  initial: () => ({
    loading: false,
    result: null,
  }),
  actions: (self) => ({
    async doSomethingAsync() {
      // actions can be async, parket doesn't care
      self.loading = true;
      self.result = await somethingAsync(); // be aware that you should handle errors
      self.loading = false;
    },
  }),
});

preact / react

import { Component } from 'preact';
import { observe, connect, Provider } from 'parket/preact'; // or 'parket/react'

// observe keeps the component updated to models in the prop @observe class Observed extends Component { render({ person }) { // if you're using react, props don't get passed to render so you have to use const {person} = this.props; return (

{person.fullname}

); } }

// connect inserts the store/instance into props @connect class Person extends Component { render({ store }) { // if you're using react, props don't get passed to render so you have to use const {store} = this.props; return (

{store.fullname}

); } }

// Provider adds an instance to the context const root = () => (

);

preact / react hooks

function Observed({ person }) {
  useObserved(person);

return (

{person.fullname}

); }

function Person() { const store = useStore();

return (

{store.fullname}

); }

// Provider adds an instance to the context const root = () => (

);

Credits

License

MIT © hrmny.sh

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.