laojun / cube-state

A tiny state management library based on React Hook which similar to dva

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

English | 简体中文

cube-state

A React state management library Based on Hooks which inspired by stamen

npm version Bundle Size React

Features

  • Perfect Typescript support
  • API and structure similar to dva
  • tiny

Try It Online

Edit

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]);

About

A tiny state management library based on React Hook which similar to dva

License:MIT License


Languages

Language:TypeScript 93.2%Language:JavaScript 6.8%