A state management with promise middleware, immutable data and model normalization
Features
- Express-like and promise-based middlewares and routers. See Middleware and Router
- Immutable state and operations. See Immutable State
- Model support to normalize data and operate like database. See Model
Example
// store.js;; const store = users: ; store;store; store; moduleexports = store; // router.js;const router = ; routerall'/users/query' async { const User = store; const offset limit = reqbody; const result = await ; store;}; routerall'/users/:userId/posts/create' async { const User = store; const Post = store; const userId = reqparams title = reqbody; const result = await ; store;}; moduleexports = router; // UserListPage.js;; static propTypes = users: PropTypesarrayisRequired dispatch: PropTypesfuncisRequired { const users = thisprops; return <ul> users </ul>; } moduleexports = UserListPage; // index.js;;;; ReactDom;
Installation
yarn add stas react-stas -S
or if your'd like to use npm:
npm install stas react-stas -S
Middleware
store.use((req, store, next)=>{})
Router
Like express router but with promise support. For detail see uni-router
router.use(pattern?: string, middleare)
Prefix match req.url
with pattern
router.all(pattern?: string, middleare)
Exact match req.url
with pattern
Immutable State
It's using plain-immutable to make the state immutable. plain-immutable
is a simple immutable library with array and plain object compatible.
; const arr = ;arr0 = -1; // it will throwarr2a = 'c'; // it will throw too even you want to change the nested object console;// bconsole;// [1,2,{"a":"b"}] const mArr = arr;console;// 1console;// -1
Model
Model is used to hold structured data and maintain their relationships. In short, it lets you operate like a database. In the real world app, data are mostly consisted of nested objects. See a post with user and comments:
const post = id: 1 title: 'Hello' author: id: 1 name: 'Tian' comments: id: 1 text: 'Up' creater: id: 2 name: 'Jian' id: 2 text: 'Thanks' creater: id: 1 name: 'Tian' ;
If we want to change the user's name, many locations need to check and change, which is terrible! So we use models to flatten the structure, and use id to keep the records' relationships.
const store = post: null ; store;store;store; store; console; // {post: 1}console;// { Post: { '1': { id: 1, title: 'Hello', author: 1, comments: [Object] } },// User: { '1': { id: 1, name: 'Tian' }, '2': { id: 2, name: 'Jian' } },// Comment:// { '1': { id: 1, text: 'Up', creater: 2 },// '2': { id: 2, text: 'Thanks', creater: 1 } } }
.get(id)
Get the record(s). If you pass an array of ids, it will return an array of records. The return is always immutable.
.set(record)
Add or replace the record in database.
.merge(input)
Normalize the input data and merge to database. Return the id or ids(if input is array).
.remove(id)
Remove the record(s)
Hot Reload(HMR)
Since react-native doesn't support module.hot.accept(path, callback)
but module.hot.accept(callback)
, we have to use a function to export the store, then replace store's middlewares(routers) by utilizing closure.
;; { const store = store; if modulehot modulehotaccept { const newRouters = default; store; store; }; return store;}
Contributing
Checkout the CONTRIBUTING.md if you want to help
License
Licensed under MIT
Copyright (c) 2017 Tian Jian