2.0.1 • Published 2 years ago

@xdoer/state-bus v2.0.1

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

StateBus

React 下一个简单的状态共享工具

安装

npm install @xdoer/state-bus --save

使用

  1. 组件外部初始化一个 StatusBus 对象。
  2. 组件内部使用 StatusBus 对象上的 useState 方法。
import StateBus from '@xdoer/state-bus';

const store = StateBus.create<number>(0);
// 或者
const store = StateBus.create<number>(() => 0);

const Profile1 = () => {
  const [count, setCount] = store.useState();

  return (
    <div>
      <div>count: {count}</div>
      <div onClick={() => setCount(i => i + 1)}>setCount</div>
    </div>
  );
};

const Profile2 = () => {
  const [count, setCount] = store.useState();

  return (
    <div>
      <div>count: {count}</div>
      <div onClick={() => setCount(i => i + 1)}>setCount</div>
    </div>
  );
};

Set/Get

通过 StateBus 对象上的 getStatesetState,可以实现在任意地方获取和变更状态

const store = StateBus.create<number>(0);

const Button = () => {

  function onClick() {
    const count = store.getState()

    store.setState(count + 1)
  }

  return (
    <div onClick={onClick}>
      点击
    </div>
  );
};

createShareHook

createShareHook 是一件简单的闭包函数,允许你创建高阶 Hook,产生的状态在所有组件中共享。

import { createShareHook } from '@xdoer/state-bus';

const useCount = createShareHook(
  // 函数参数是一个 StateBus 对象
  store => {
    const [count, setCount] = store.useState();
    return { count, setCount };
  },
  // 初始化数据
  0
);

const useCount = createShareHook(
  // 函数参数是一个 StateBus 对象
  (store) => {
    const [count, setCount] = store.useState();
    return { count, setCount };
  },
  // 初始化数据
  () => 0
);

可以根据 useCount.store 对状态进行 get/set 操作

// 获取状态
useCount.store.getState()

// 设置状态
useCount.store.setState(1)

装载与卸载

StateBus 暴露了一个 hooks 对象,对象上有 onMountonUnMount 事件。

const store = StateBus.create<number>(0);

// 第一个组件加载时执行
store.hooks.onMount = () => {}

// 最后一个组件卸载时执行
store.hooks.onUnMount = () => {}

const Profile = () => {
  const [count, setCount] = store.useState();
  return <div>{count}</div>;
};

export default function App() {
  return (
    <>
      <Profile /> // 组件 mount 时,执行 store.hooks.onMount
      <Profile />
      <Profile /> // 组件 unMount 时,执行 store.hooks.onUnMount
    </>
  )
}

onMount

onMount 一般用来初始化只需要执行一次的异步代码,比如发起 HTTP 请求后,更新所有相关组件状态。

const useUser = createShareHook((store) => {
  const [user, setUser] = store.useState()

  store.hooks.onMount = async () => {
    const res = await fetch('/user')
    const user = await res.json()
    setUser(user)
  }

  return { user }
})

而若要初始化同步代码,由于其他组件还没有 mount, 所以在 onMount 中更新状态无效。

const useUser = createShareHook((store) => {
  const [user, setUser] = store.useState()

  store.hooks.onMount = async () => {
    const user = getUserInfoSync()
    // 操作无效
    setUser(user)
  }

  return { user }
})

初始化同步代码需要在创建 StateBus 对象时,传进去就可以。

const useUser = createShareHook(
  (store) => {
    const [user, setUser] = store.useState()
    return { user }
  },
  () => getUserInfoSync()
)

// 或者
const userStore = StateBus.create(getUserInfoSync())

// 或者
const userStore = StateBus.create(() => getUserInfoSync())

onUnMount

onUnMount 一般用于清除缓存数据的一些操作

const globalCache = {}

const useUser = createShareHook((store) => {
  const [user, setUser] = store.useState()

  store.hooks.onMount = async () => {
    const res = await fetch('/user')
    const user = await res.json()
    globalCache['user'] = user
  }

  store.hooks.onUnMount = async () => {
    delete globalCache['user']
  }

  return { user }
})

基于 StateBus 实现的共享状态的请求库: useRequest

useStore

useStore 不再需要在组件外部初始化 StateBus。使用与 useState 类似,但是不同的是,需要你指定一个 key.

import { useStore } from '@xdoer/state-bus';

function useCount() {
  const [count, setCount] = useStore('count', '1')
  return { count, setCount }
}

const Profile1 = () => {
  const { count, setCount } = useCount()

  return (
    <div>count: {count}</div>
  );
};

const Profile2 = () => {
  const { count, setCount } = useCount()

  return (
    <div>count: {count}</div>
  );
};

getStore/setStore

getStore 允许你在任意地方,获得 useStore 状态数据

const Button = () => {
  const [count, setCount] = useState()

  function onClick() {
    // 根据 key 得到状态
    const storeCount = getStore('count')

    setCount(storeCount)
  }

  return (
    <div onClick={onClick}>
      storeCount: {count}
    </div>
  );
};

setStore 允许你在任意地方,更新 useStore 状态数据

const Button = () => {

  function onClick() {
    setStore('count', 1)

    setStore('count', prev => prev + 1)
  }

  return (
    <div onClick={onClick}>
      click
    </div>
  );
};

扩展

持久化状态到异步 storage

class StorageState<T = any> extends StateBus<T> {
  constructor(private key: string, init?: T | (() => T)) {
    super(init);
  }

  async getState(): Promise<T> {
    const state = super.getState();
    const storage: any = await getStorage(this.key);

    if (!isUndefined(storage)) {
      if (state !== storage) {
        super.setState(storage as any);
      }
      return storage;
    }

    if (!isUndefined(state)) {
      await setStorage({ key: this.key, data: state });
    }

    return state;
  }

  async setState(state: any) {
    super.setState(state);
    await setStorage({ key: this.key, data: state });
  }
}
2.0.1

2 years ago

2.0.0

2 years ago

1.3.0

2 years ago

1.2.0

2 years ago

1.1.0

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago