Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ForsakenHarmony/parket
A library to manage application state, heavily inspired by mobx-state-tree
https://github.com/ForsakenHarmony/parket
Last synced: 3 months ago
JSON representation
A library to manage application state, heavily inspired by mobx-state-tree
- Host: GitHub
- URL: https://github.com/ForsakenHarmony/parket
- Owner: ForsakenHarmony
- Created: 2018-01-23T21:34:39.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T03:15:56.000Z (about 2 years ago)
- Last Synced: 2024-11-13T00:03:44.738Z (3 months ago)
- Language: TypeScript
- Size: 2.51 MB
- Stars: 434
- Watchers: 10
- Forks: 17
- Open Issues: 44
-
Metadata Files:
- Readme: README.md
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
- awesome-list - parket - state-tree | ForsakenHarmony | 437 | (TypeScript)
README
![]()
- 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
``````js
// 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
```js
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
```js
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
```js
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
```js
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
- [Mobx State Tree for Inspiration](https://github.com/mobxjs/mobx-state-tree)
- [Zouhir for the awesome logo](https://twitter.com/_zouhir)## License
[MIT © hrmny.sh](https://oss.ninja/mit/forsakenharmony)