Magicist
Extra simple state manager.
No need to think about details. Just write code
Table of Contents
- Advantages
- Installation
- Introduction
- Examples
- Demo - Basic
- API
- What will Magicist react to?
- Contributing
Advantages
- Zero-dependency
- Tiny bundle size (1 KB gzipped)
- Boilerplate free
- React bindings out of the box
- Async actions management out of the box
- Only point changes (you no longer need to reduce the state)
- With Magicist you don't need to normalize your data. This makes the library very suitable for very complex domain models
- No need classes, decorators
- No need immutable data structures
Installation
Via yarn
yarn add magicist
Via npm
npm install magicist --save
Introduction
Magicist works by simple cycle, see illustration below
Examples
Increment/decrement
import React from 'react';
import {createStore} from "magicist";
import {useStore} from "magicist";
export const counterStore = createStore({
count: 0,
increment: function () {
this.count++;
},
decrement: function () {
this.count--;
},
reset: function() {
this.count = 0;
}
});
const Counter = () => {
let {count, increment, decrement, reset} = useStore(counterStore);
return (
<>
<div>Counter {count}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</>
);
};
Demo
Basic
API
createStore
createStore(model, middlewares)
Create a store object that holds the state tree.
Arguments
model
: Objectmiddlewares
: Array<(model: Object, func: (any) => any, args: Array) => void>
Returns
Store
object that holds the state tree.
Example
const store = createStore({
someData: 100
});
middlewares
These are functions that intercept actions. Middlewares are will be called before running the store functions.
Middleware function arguments:
model
: Modelfunc
: Functionargs
: arguments to be passed in called function
Example
function logger(model, func, args) {
console.log(model); // {someData: 100, manipulateData: (...)}
console.log(func); // ƒ (receivedData) { return this.someData / receivedData; }
console.log(args); // [100]
}
const middlewares = [logger];
const store = createStore({
someData: 100,
manipulateData: function(receivedData) {
return this.someData / receivedData;
}
}, middlewares);
store.getModel().manipulateData();
watch
watch(watcher)
Triggers the callback when store is updated
Arguments
watcher
: (model: Model) => void
Returns
disposer
function, which can be used to dispose of the watcher when you no longer need it.
Example
const globalStore = createStore({
count: 0,
increment: function () {
this.count++;
}
});
const watcher = model => console.log(model);
const disposer = globalStore.watch(watcher); // { count: 1, increment: (...) }
globalStore.getModel().increment();
disposer(); // unsubscribe from updates
watchProp
watchProp(propName, watcher)
Triggers the callback when store's prop is updated
Arguments
watcher
: (oldValue, newValue) => void
Returns
disposer
function, which can be used to dispose of the watcher when you no longer need it.
Example
const globalStore = createStore({
count: 0,
increment: function () {
this.count++;
}
});
const watcher = (oldValue, newValue) => console.log(oldValue, newValue);
const disposer = globalStore.watchProp('count', watcher); // 0, 1
globalStore.getModel().increment();
disposer(); // unsubscribe from updates
useStore
useStore(store)
Creates hook function, which subscribe to watcher, that observes changes in current store, so when recording results, the component will update automatically.
Arguments
store
: Store (created bycreateStore
)
Returns
Model
Example
let model = useStore(store);
What will Magicist react to?
Magicist reacts to any existing observable property that is read during the execution of a tracked function.
Contributing
- Feel free to send pull requests.
- Use
yarn test
to run the basic test suite.