Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

redux-saga-model

Package Overview
Dependencies
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redux-saga-model

此项目为从 [`dva`](https://github.com/dvajs/dva) 中抽取出对 model 的处理。

  • 0.1.3
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
2
decreased by-66.67%
Maintainers
1
Weekly downloads
 
Created
Source

redux-saga-model

此项目为从 dva 中抽取出对 model 的处理。

npm i --save redux-saga-model

or

yarn add redux-saga-model

why

在 redux 的初期使用中,我们在 react 组件中进行异步处理,并在 then 中同步分发 action,在 reducer 中实时更新数据,但这样容易出现冗余代码且不易于后期维护,后前我们使用了 redux-thunk ,将每个 thunk 作为异步处理的流程块 ,随着业务的复杂我们发现对于更复杂的流程控制,redux-thunk 也是力不从心,接着我们发现了 redux-saga,并对其强大的异步处理流程控制着迷,但这个时候我们发现我们的每个模块单元下的目录结构如下:

|
  |--components/
  |--action.js
  |--reducer.js
  |--router.js
  |--selector.js
  |--saga.js
  |...

我们发现了 dva,这个强大的框架将 saga.js 与reducer.js 进行了有效的结合:

|
  |--components/
  |--action.js
  |--model.js
  |--router.js
  |--selector.js
  |...

每个 model 都有独立的维护机制,各自负责属于自己的一块 state-tree。每个 model 将对其独立的 state-tree 进行维护的 reducers 进行封装,同时把负责业务逻辑的 saga 放入 model 中,并为每个 model 增加 namespace 。看起来的确很完美,但是我们发现其中这个 model (我们统称为 saga-model) 的处理( dva )与 react 进行了捆绑,同时由于我们有一套自己实现的项目启动工具,想要将这个 saga-model 的优秀思想进行结合。故我们将其进行抽取,同时进行改造。

改变

  • 独立出来的 model 处理器成为 sagaModel ,通过实例化 SagaModel 拿到 sagaModel。

  • 可以很明显的入参 initialState initialReducer initialMiddleware 而不需要 dva 那样晦涩。

  • ​ 每个 model 中的代码结构如下:

    {
      namespace:'index',
      state:{
        name:'Tim'
      },
      reducers:{
        update:function(state,{payload}){
          return{ ...state,name:payload.name };
        }
      },
      sagas:{
        *updateName({payload},effects){
          yield effects.put({
              type:'update',
              payload,
            });
        }
      }
    }
    

    可以发现与 dva 的 model 基本一致,但是把 dva 中的 model 的 effects 字段换成了 sagas 因为根据 redux-saga 的官方文档介绍,这个叫法更符合其用意。

    同理,在 plugins 中,也将 dva 中的 onEffect 改成了 onSaga

    this.hooks = {
      onError: [],
      onStateChange: [],
      onAction: [],
      onHmr: [],
      onReducer: [],
      onSaga: [],
      extraReducers: [],
      extraEnhancers: [],
    };
    
  • 在每个 model 内的 saga,默认执行类型是 takeEvery 可以像 dva 一样将每个 saga 传入数组格式,更换其执行类型:

    {
      namespace:'index',
      state:{
        name:'Tim'
      },
      reducers:{
        update:function(state,{payload}){
          return{ ...state,name:payload.name };
        }
      },
      sagas:{
        updateName:[*({payload},effects)=>{
          yield effects.put({
              type:'update',
              payload,
            });
        },{ type: 'takeEvery' }],
        updateAddress:[*({payload},effects)=>{
          yield //...
        },{ type: 'takeLatest' }]
      }
    }
    

    支持的类型与 dva 相同 watcher takeLatest throttle takeEvery 默认是 takeEvery 在 dva 中,每个 saga 都允许省略当前 model 的 namespace 前缀直接分发( put )当前 reducer 的名字作为 actionType ,但是同样的特性不支持 take( 在 watcher 中自己决定接受什么 action),这里将其改进为支持该特性。

    {
      namespace:'index',
      state:{
        name:'Tim'
      },
      reducers:{
        update:function(state,{payload}){
          return{ ...state,name:payload.name };
        }
      },
      sagas:{
        watchUpdateName:[*({payload},effects)=>{
          // yield effects.take('index/update_name');
          yield effects.take('update_name');
          yield effects.put({
              type:'update',
              payload,
            });
        },{ type: 'watcher' }],
    }
    
  • 为每个 saga 内部的 this 提供指向当前的 model。

  • 不再提供与 react,react-router 的绑定,在 dva 中可以直接 start 启动,而这里需要你自己根据实际情况进行处理, 实例化 SagaModel 后通过 sagaModel 的 store 方法获取配置完成的 store,自己进行下一步的处理,如需要与 react-router 进行绑定,可以参考 react-router-redux-saga-model 以及其对应的案例。

  • API 的命名改变,具体如下。

API

  • SagaModel model 处理器类,处理过程与 dva基本相似,入参均为可选:

    • initialState :Object 传入 createStore 的默认 state

    • initialReducer :Object 不包含在 model 中的其他 reducers

    • initialMiddleware :Array 其他 middleware, logging 等各种

    • initialModels :Array 在获取 store 时启动所有的 model,正常情况下推荐使用改默认入参将所有的 model 进行启动,如果需要异步启动可以使用 sagaModel.register 方法。

    • history :Object 通过 history 构造的实例,可以用于在 model 的 substrtions 中使用。

    import {SagaModel} from 'redux-saga-model';
    const sagaModel = new SagaModel({initialState, initialReducer, initialMiddleware, initialModels,history});
    
    const store = sagaModel.store();
    
  • sagaModel.use 使用插件

    import sagaModel from 'redux-saga-model';
    import someCrossSliceReducer from 'somewhere';
    import reduceReducers from 'reduce-reducers'
    
    sagaModel.use({
        onReducer:(reducer)=>{
          return reduceReducers(reducer, someCrossSliceReducer);
        },
      	//...
    })
    

    插件类型:如前面所述,基本与 dva 一致,除了把 onEffect 改成了 onSaga

    hooks = {
      onError: [],
      onStateChange: [],
      onAction: [],
      onHmr: [],
      onReducer: [],
      onSaga: [],
      extraReducers: [],
      extraEnhancers: [],
    }
    
  • sagaModel.plugin 获取所有插件

    import sagaModel from 'redux-saga-model';
    
    const plugins = sagaModel.plugin();
    
  • sagaModel.setHistory 设置 history

    import createBrowserHistory from "history/createBrowserHistory";
    import sagaModel from 'redux-saga-model';
    
    sagaModel.setHistory(createBrowserHistory());
    
  • sagaModel.history 获取 history

    import createBrowserHistory from "history/createBrowserHistory";
    import {ConnectedRouter} from "react-router-redux";
    import sagaModel from 'redux-saga-model';
    
    sagaModel.setHistory(createBrowserHistory());
    
    export default (props)=>{
        return (
        	<ConnectedRouter history={sagaModel.history()}>
              { props.children }
            </ConnectedRouter>
        );
    }
    
  • sagaModel.store 获取配置完成的 store,并启动所有的已存在的 models

    import {Provider} from "react-redux";
    import sagaModel from 'redux-saga-model';
    import APP from './app';
    
    export default ()=>{
        return (
          <Provider store={sagaModel.store()}>
            <APP />
          </Provider>
      );
    }
    
  • sagaModel.register 注册一个 model,可以在任何时刻调用。

    import sagaModel from 'redux-saga-model';
    import userModel from 'users/userModel';
    import indexModel from 'index/indexModel';
    import todoModel from 'todo/todoModel';
    
    sagaModel.register(indexModel);
    
    const store = sagaModel.store();
    
    sagaModel.register(todoModel);
    
    new Promise((resolve,reject)=>{
        setTimeout(()=>{
            sagaModel.register(userModel);
          	resolve();
        },1000);
    });
    
  • sagaModel.dump 卸载一个指定 namespace 的 model

    import userModel from 'users/userModel';
    import sagaModel from 'redux-saga-model';
    
    sagaModel.register(userModel);
    sagaModel.dump(userModel.namespace);
    
  • sagaModel.models 获取所有的 models

    import sagaModel from 'redux-saga-model';
    
    console.log(sagaModel.models().length);
    
  • 其他内部 API

用例

react-router-redux-saga-model

指南

redux-saga-model-tutorial

FAQs

Package last updated on 17 Aug 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc