1.0.0 • Published 4 years ago

@tinytot/use-store v1.0.0

Weekly downloads
1
License
ISC
Repository
github
Last release
4 years ago

useStore

npm (scoped) build Coverage Status NPM downloads npm bundle size (scoped) npm peer dependency version

基于 React Hooks 的轻量级中心化数据管理方案。

安装

$ npm install @tinytot/use-store -S
# or
$ yarn add @tinytot/use-store

使用

1. 中心化的 models 定义

// src/models/count.js
export default {
  name: "count",
  state: {
    count: 0,
  },
  actions: {
    add(value, state) {
      state.count = value;
    },
    async fetchData(value, state) {
      state.count = await Promise.resolve(value);
    },
  },
};

2. models 绑定

import { createSharedStateContext } from "@tinytot/use-store";

import countModel from "./models/count";

import Counter from "./src/components/Counter";
import List from "./src/components/List";

const Context = createSharedStateContext();

ReactDOM.render(
  <Context.Provider models={[countModel]}>
    <Counter />
    <List />
  </Context.Provider>,
  document.getElementById("root")
);

3. 在组件中访问 state 和 actions

// src/components/Counter.js
import { useStore, useStatus } from "@tinytot/use-store";

export default () => {
  const [count, dispatch] = useStore("count", (s) => s.count);
  const [status] = useStatus("count.fetchData");
  const handleClick = () => {
    dispatch("add", 1);
  };
  const handleFetchDataClick = () => {
    dispatch("fetchData", 1);
  };
  return (
    <div>
      {Math.random()}
      <div>
        <div>Count: {count}</div>
        <div>{status.pending ? "pending" : ""}</div>
        <button onClick={handleClick}>add 1</button>
        <button onClick={handleDetchDataClick}>async add 1</button>
      </div>
    </div>
  );
};

// src/components/List.js
import { useStore } from "@tinytot/use-store";

export default () => {
  const [count] = useStore("count", (s) => s.count);
  return (
    <div>
      {Math.random()}
      <div>
        <div>Count: {count}</div>
      </div>
    </div>
  );
};

API

createSharedStateContext

createSharedStateContext 是创建 Context

import { createSharedStateContext } from "@tinytot/use-store";
const Context = createSharedStateContext();

const Root = () => <Provider models={[model1, model2]}>...</Provider>;

ReactDOM.render(<Root />, document.getElementById("root"));

useStore<T = State>(name: string, selector: ((state: State) => T) = (s: State) => (s as T), isEqual = looseEqual): T, StoreDispatch

自定义 hook,以元组的形式返回store中最新的state和可触发actionsdispatch方法集合。

  • name: model名称
  • selector:用于从store里提取所需数据的一个纯函数(不传则返回整个state对象),强烈推荐传入selector按需提取数据,这样可以保证只有被提取的state值改变时组件才会re-render
  • isEqual:前后两次提取的state值对比函数,只有值改变才会re-render组件

直接修改返回的state是不安全的(修改不会被同步更新到组件),只有action函数和中间对state的修改是安全的!

useStatus(name.action) => { pending: boolean, error: Error }

useStatus hook,用于监听(异步)action的执行状态,返回pendingerror两个状态,当action正在执行时pending=true,当执行出错时error为具体错误对象,当执行状态发生变化时会同步更新到DOM

model 定义

model是普通的javascript对象,类型申明:

interface Model {
  readonly name: string; // name of model
  state?: {}; // model state
  readonly actions: {
    [action: string]: <T = any>(value: T, state: State) => void | Promise<void>;
  };
}
1.0.0

4 years ago

0.1.0

4 years ago