reax-hook
TypeScript icon, indicating that this package has built-in type declarations

3.1.3 • Public • Published

reax-hook

reax-hook是利用React Hook配合Context和useReducer封装的一个用于小型模块的状态管理库,提供类似vuex的语法。

reax-hook is a React Hook state manager realized by Context and useReducer.

安装

npm install reax-hook -S

稳定性

Build Status Coverage Status

为什么用它

  1. 带给你Vuex类似的语法。
  2. 完善的TypeScript类型推导。
  3. 测试覆盖率100%

文档

https://sl1673495.github.io/reax-hook/

更新 3.0

  1. 全面使用TypeScript重构

  2. 脚手架工具使用umi团队的father

  3. 基于docz的文档

更新 2.0

  1. 新增测试用例,测试覆盖率达到100%

  2. mutation 的函数参数顺序和 Vuex 保持一致

  mutations: {
    // 浅拷贝state
    add(state, payload) {
      return Object.assign({}, state, { count: state.count + 1 })
    },
  },
  1. actions 的函数参数和vuex保持一致
  actions: {
    async asyncAdd({ dispatch, state, getters }, payload) {
      await wait(100)
      dispatch({ type: 'add' })
      // 返回的值会被包裹的promise resolve
      return true
    },
  },

适用场景

比较适用于单个比较复杂的小模块,个人认为这也是 react 官方推荐 useReducer 和 context 配合使用的场景。 由于所有使用了 useContext 的组件都会在 state 发生变化的时候进行更新(context 的弊端),推荐渲染复杂场景的时候配合 useMemo 来做性能优化。

编写 store

// store.js
import initStore from 'reax-hook'
 
export const { connect, useStore } = initStore({
  // 初始状态
  initState: {
    count: 0,
  },
  // 同步操作 必须返回state的拷贝值
  mutations: {
    // 浅拷贝state
    add(state, payload) {
      return Object.assign({}, state, { count: state.count + 1 })
    },
  },
  // 异步操作,拥有dispatch的执行权
  actions: {
    async asyncAdd({ dispatch, state, getters }, payload) {
      await wait(1000)
      dispatch({ type: 'add' })
      // 返回的值会被包裹的promise resolve
      return true
    },
  },
  // 计算属性 根据state里的值动态计算
  // 在页面中根据state值的变化而动态变化
  getters: {
    countPlusOne(state) {
      return state.count + 1
    },
  },
})
 
 
// 注意这里不要提前声明好配置对象然后传递给initStore
// 否则由于ts的限制会失去类型推断

在页面引用

// page.js
import React, { useMemo } from 'react'
import { Spin } from 'antd'
import { connect, useStore } from './store.js'
 
function Count() {
  const { state, getters, dispatch } = useStore()
  const { countPlusOne } = getters
  const { loadingMap, count } = state
  // loadingMap是内部提供的变量 会监听异步action的起始和结束
  // 便于页面显示loading状态
  // 需要传入对应action的key值
  // 数组内可以写多项同时监听多个action
  // 灵感来源于dva
  const loading = loadingMap.any(['asyncAdd'])
 
  // 同步的add
  const add = () => dispatch({ type: 'add' })
 
  // 异步的add
  const asyncAdd = () => dispatch.action({ type: 'asyncAdd' })
  return (
    <Spin spinning={loading}>
      <span>count is {count}</span>
      <span>countPlusOne is {countPlusOne}</span>
      <button onClick={add}>add</button>
      <button onClick={asyncAdd}>async add</button>
 
      {/** 性能优化的做法 * */}
      {useMemo(
        () => (
          <span>只有count变化会重新渲染 {count}</span>
        ),
        [count]
      )}
    </Spin>
  )
}
 
// 必须用connect包裹 内部会保证Context的Provider在包裹Count的外层
export default connect(Count)

Package Sidebar

Install

npm i reax-hook

Weekly Downloads

1

Version

3.1.3

License

ISC

Unpacked Size

17.9 kB

Total Files

9

Last publish

Collaborators

  • sl1673495