English | 简体中文
cube-state
A React state management library Based on Hooks which inspired by stamen
Features
- Perfect Typescript support
- API and structure similar to dva
- tiny
Try It Online
Install
npm install --save cube-state
# Or
yarn add cube-state
Quick Start
Init
first of all, do some init job, like extend effect or patch every store when created. you can see the Advanced Usages.
init-cube.ts
import init from "cube-state";
const { createStore, createFlatStore, storeMap, use } = init();
export { createStore, createFlatStore, storeMap, use };
Create store
Pass a plain config to createStore
and get a wrapped store object.
or use createFlatStore
to flatten reducers and effects to store object.
stores/counter.ts
import { createStore } from "init-cube";
export default createStore({
name: "count",
state: {
count: 0
},
reducers: {
add(state) {
state.count += 1;
}
},
effects: {}
});
Use store
Call useStore
to watch selected data change and re-render.
import counterStore from "stores/counter";
function App(props) {
const value = counterStore.useStore(s => s.count);
return (
<div>
<p>{value}</p>
<button onClick={() => counterStore.reducers.add()}>Increment</button>
</div>
);
}
Plugin
loading
use loading plugin to toggle loading status
import loadingStore from 'cube-state/dist/plugin/loading';
import userStore from 'stores/user';
function MsgList() {
const { getMsgList } = userStore.effects;
const loading = loadingStore.useSpace(userStore);
React.useEffect(() => {
getMsgList();
}, []);
return <Spin loading={loading.getMsgList}><div>msg list</div><Spin>
}
devtools
use redux devtools to watch data change detail
import devtools from 'cube-state/dist/plugin/dev-tool';
devtools({ storeMap, use });
Advanced Usages
Pass initial config
import init from "cube-state";
const cube = init({
extendEffect({ storeMap, update }) {
// extend effect first argument
},
onCreate(store) {
// do some job after store is created
}
});
Use data without subscribe change
use getState
instead of useStore
if you don't want to rerender component when store changed;
getState
is not Hook, you can use it anywhere.
import counterStore from "stores/counter";
export function doubleCount() {
return 2 * counterStore.getState(s => s.count);
}
Use in class components
you have to wrap class component by functional component. will provide some util function later.
import counterStore from "stores/counter";
interface IProps {
value: typeof counterStore.stateType.value;
add: typeof counterStore.reducers.add;
}
class Counter extends Component<IProps> {
render() {
const { value, add } = this.props;
return (
<div>
<p>{value}</p>
<button onClick={() => add}>Increment</button>
</div>
);
}
}
export default () => {
const value = counterStore.useStore(s => s.count);
return <Counter value={value} add={counterStore.reducers.add} />;
};
Performance optimization
use selector to pick the data you want to subscribe precisely.
const [count, deepValue] = someStore.useStore(s => [s.count, s.a.deepValue]);