1 Star 0 Fork 0

一哥 / use-redux-agent

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

npm standard

注意

当前版本响应agent-reducer@3.1.0+版本的号召,支持agent-reducer@1.*特性及写法, 只需要对老版本modules使用 legacy 方法即可。 use-redux-agent不受agent-reducer全局环境设置 (globalConfig)env.legacy 影响。

use-redux-agent

redux

作为一个状态管理工具,redux非常的优异,在全局数据管理方面尤为突出。而redux使用的数据处理机制 reducer 更是让热衷于函数式编程的程序员爱不释手, 甚至连 react 官方也推出了 useReducer 作为非全局数据管理的替代品。但 reducer 也有一些小缺点,比如需要通过 dispatch 事件分发来管理状态。 这里我们使用 agent-reducer 语法糖,让 reducer 的使用更接近于对象方法调用,更加自然方便。

关于 agent-reducer

换种写法

import {OriginAgent} from "agent-reducer";

    interface Action {
        type?: 'stepUp' | 'stepDown' | 'step' | 'sum',
        payload?: number[] | boolean
    }

    /**
     * 经典reducer
     * @param state
     * @param action
     */
    const countReducer = (state: number = 0, action: Action = {}): number => {
        switch (action.type) {
            case "stepDown":
                return state - 1;
            case "stepUp":
                return state + 1;
            case "step":
                return state + (action.payload ? 1 : -1);
            case "sum":
                return state + (Array.isArray(action.payload) ?
                    action.payload : []).reduce((r, c): number => r + c, 0);
            default:
                return state;
        }
    }

    /**
     * class写法
     */
    class CountAgent implements OriginAgent<number> {

        state = 0;
        
        stepUp = (): number => this.state + 1;

        stepDown = (): number => this.state - 1;

        step = (isUp: boolean) => isUp ? this.stepUp() : this.stepDown();

        sum = (...counts: number[]): number => {
            return this.state + counts.reduce((r, c): number => r + c, 0);
        };

    }

以上代码是一段简单的计数器,CountAgent通过调用对象属性方法的形式来完成一个reducer action分支, return值作为计算完后的this.state数据(这里并未涉及state维护器,所以先当作有这么一个黑盒工具)。 有点像reducer,但省去了action的复杂结构(action为了兼容多个分支的不同需求所以很难以普通传参方式来工作)。

用在 redux 上

可参考例子

module 业务数据模型:module/count.ts

import {middleWare,MiddleWarePresets, OriginAgent} from "agent-reducer";

class CountAgent implements OriginAgent<number> {

    // 全局统一初始化数据方法,在调用 use-agent-redux 提供的 initialStates 方法时被统一调用,
    // 并把 resolve 或 return 非promise 的数据 dispatch 到 store中相应的 state 中
    static initialState(){
        return Promise.resolve(1);
    }

    // 初始化的state数据,根据redux要求不能为 undefined
    state = 0;
        
    // 方法调用后的返回值被 dispatch 到 store相应的 state 中,并成为当前的 this.state
    stepUp = (): number => this.state + 1;

    stepDown = (): number => this.state - 1;

    step = (isUp: boolean) => isUp ? this.stepUp() : this.stepDown();

    sum(...counts: number[]): number {
        return this.state + counts.reduce((r, c): number => r + c, 0);
    };

    // 返回对象为 promise ,如果没有使用 agent-reducer 的 MiddleWare,
    // this.state 将变成一个 promise 对象。
    // 这里使用了 MiddleWarePresets.takePromiseResolve() 将 promise resolve 的数据dispatch出去,
    // 并成为 this.state
    @middleWare(MiddleWarePresets.takePromiseResolve())
    async requestAndSum(){
        const remote=await Promise.resolve(3);
        return this.sum(remote); 
    }   

}

关于 agent-reducer 模型及 MiddleWares 的使用,可以参考: agent-reducer

root 创建 store,并将模型reducer化 module/index.ts

import {createStore} from "redux";
import count from './count';
import {createReduxAgentReducer} from "use-redux-agent";

const modules={
    count
};

// 将modules打包成一个reducer方法
const reducer = createReduxAgentReducer(modules);

// 使用 redux 的 createStore 和绑定好的 reducer 创建 store,
// reducer.enhancer 是必要的,用来组建 store 和 agent 的关系
const store = createStore(reducer, reducer.enhancer);

export default store;

total layout 将store加入react-redux的Provider layout.tsx


import React, {useEffect} from 'react';
import {Provider} from 'react-redux';
import store from './module';
import {initialStates} from "use-redux-agent";
import Apply from './apply.tsx'

export default () => {
    useEffect(()=>{
        // 初始化所有具备 static
        initialStates(store);
    },[]);
    return (
        <Provider store={store}>
            <Apply/>
        </Provider>
    );
}

apply 应用,监听数据变化触发渲染(组件中获取最新数据)、dispatch action apply.tsx

import React ,{useEffect}from 'react'; 
import Count from './module/count.ts'
import {useReduxAgent} from "use-redux-agent";

export default ()=>{
    // useReduxAgent 直接传入 Module 的 class 模型就可以取到 agent 了
    // agent 的 state 就是 store 中对应当前模型的 state,所有方法调用都有自动dispatch action功能
    const {state,stepUp,stepDown,requestAndSum}=useReduxAgent(Count);

    useEffect(()=>{
        requestAndSum();
    },[]);

    return (
        <div>
            <button onClick={stepUp}>stepUp</button>
            <span>{state}</span>
            <button onClick={stepDown}>stepDown</button>
        </div>
    );
}

为什么不用namespace,因为 use-redux-agent 认为 class 直接代表了模型, 只要取到模型就应该可以拿到相关数据,并可以直接操作才对,所以与普世的redux作风有所不同。

agent-reducer 是 use-redux-agent 的基础。 要想更容易的使用 use-redux-agent ,建议可以参考 agent-reducer 文档。关于 MiddleActions 的使用,建议可以引入 use-agent-reduceruseMiddleActions 功能。

API

1 . createReduxAgentReducer

创建一个 reducer 方法,该 reducer 带有一个 redux 标准的 enhancer 用于组合 store, reducer, agent 之间的关系。

入参:modules object,一个由一个或多个 module class 组成的 object 模型。 每个 module class 是一个origin-agent( agent-reducer 定义 ),这个 class 的 state 来自redux存储的模型数据, class 实例方法调用相当于 dispatch action,而 static 方法 initialState,可以通过API的另一个方法initialStates(store)统一调用。

返回:reducer方法,方法reducer.enhancer是一个标准的redux createStore enhancer。

返回后使用方式:

import {createStore} from "redux";
import module from './module';
import {createReduxAgentReducer} from "use-redux-agent";

const modules={
    module
};

// 将modules打包成一个reducer方法
const reducer = createReduxAgentReducer(modules);

// 使用 redux 的 createStore 和绑定好的 reducer 创建 store,
// reducer.enhancer 是必要的,用来组建 store 和 agent 的关系
const store = createStore(reducer, reducer.enhancer);

export default store;

2 . initialStates

统一初始化modules state 数据的方法,所有带有 static initialState 方法的 module class 都可以被统一初始化, static 方法 initialState 放回的如果是个 promise 对象,则会使用 promise resolve 数据作为初始的 this.state, 如果返回普通对象,该对象及为初始化完成后的 this.state。

入参:redux的store

返回:promise,初始化是否全部结束,可以通过返回的promise resolve获知。

3 . useReduxAgent

通过 module class 获取对应的agent,当store对应class的module数据更新时,会触发agent同步(从而导致组件自动render), agent还可以通过调用方法来完成 dispatch 的事情。

入参:module class

返回:module class对应的agent

4 . legacy ( >=3.1.0 )

将 modules 设置成支持agent-reducer@1.*版本的 modules。

入参:modules - { [key:string] : module class }

返回:带有老版本支持标记的 modules - { [key:string] : module class [static useLegacy=true] }

当然在每个想要支持agent-reducer@1.*版本的 module class 上加上 static useLegacy=true 也是一样的效果

   import {OriginAgent} from "agent-reducer";

   class User implements OriginAgent<any>{

       static useLegacy=true;
       
       state={};

   }   

import {legacy,createReduxAgentReducer} from "use-redux-agent";
import UserModule from './user';
import RolesModule from './roles';
import {createStore} from "redux";

// 使用 legacy 方法将需要使用 agent-reducer@1.* 特性的 module classes 标记为 static 
const legacyModules = legacy({
    user:UserModule
});

const  modules={
    ...legacyModules,
    roles:RolesModule
}

// 将modules打包成一个reducer方法
const reducer = createReduxAgentReducer(modules);

// 使用 redux 的 createStore 和绑定好的 reducer 创建 store,
// reducer.enhancer 是必要的,用来组建 store 和 agent 的关系
const store = createStore(reducer, reducer.enhancer);

export default store;

可参考例子

change logs

The MIT License (MIT) Copyright (c) 2015-present Dan Abramov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

agent-reducer与redux结合使用的react-hook工具,可用来代替react-redux,获取更佳的class reducer编程体验。 展开 收起
TypeScript
MIT
取消

贡献者

全部

近期动态

加载更多
不能加载更多了
TypeScript
1
https://gitee.com/filefoxper/use-redux-agent.git
git@gitee.com:filefoxper/use-redux-agent.git
filefoxper
use-redux-agent
use-redux-agent
master

搜索帮助