redux探索:rematch

栏目: 服务器 · 发布时间: 5年前

内容简介:基于redux数据流的管理方案:Dva是蚂蚁金服开源的一个数据流管理方案,基于redux和redux-saga,简化了开发体验。Dva是一揽子的解决方案,可以使用侵入性很强的dva-cli来快速搭建项目,提供了路由层面的适配;也可以使用dva-core来引入核心的代码,减少侵入性。

redux存在的问题

  • 项目中redux的样板文件太分散,书写和维护都比较麻烦

  • 使用thunk来处理异步操作,不是那么直观

方案对比

基于redux数据流的管理方案: Dvamirrorrematch

Dva

Dva是蚂蚁金服开源的一个数据流管理方案,基于redux和redux-saga,简化了开发体验。Dva是一揽子的解决方案,可以使用侵入性很强的dva-cli来快速搭建项目,提供了路由层面的适配;也可以使用dva-core来引入核心的代码,减少侵入性。

缺点

  • 如果使用Dva的一整套框架,现有的项目会有较大的改动

  • Dva使用redux-saga来处理异步,学习成本比较高

mirror

类似于Dva的一个redux数据流方案,最新一次更新在两个月之前,一直没有发布1.0的版本

rematch

rematch的灵感来自于Dva和mirror,将两者的有点结合了起来。

优点

  • 使用了类似Dva的model文件结构,统一管理同步和异步操作

  • 通过中间键实现了async/await的方式来处理异步,舍弃了Dva中的redux-saga

  • 提供了redux的配置项,可以兼容项目中的老代码

  • 支持多个store

缺点?

  • 将model中reducers和effects的方法挂载在dispatch函数上,造成dispatch既是一个函数,又是一个对象

Rematch Mirror Dva
适用框架 所有框架 / 不使用框架 React React
适用路由 所有路由 / 不使用路由 RR4 RR3, RR4 / 不使用路由
移动端 ×
开发者工具 Redux, Reactotron Redux Redux
插件化
reducers
effects async/await async/await redux saga
effect params (payload, internals) (action, state) (action, state)
监听方式 subscriptions hooks subscriptions
懒加载模型
链式 dispatch
直接 dispatch
dispatch promises
加载插件
persist plugin
package size 14.9k(gzipped: 5.1k)|| redux + thunk: 6k(2k) 130.4k(gzipped: 33.8k) dva-core: 72.6k(gzipped: 22.5k)

rematch

API

import { init } from '@rematch/core';
  ​
  const store = init({
    models: {
      count: {
        state: 0,
        reducers: {
          add: (state, payload) => state + payload,
          del: (state, payload) => state - payload,
          'otherModel/actionName': (state, payload) => state + payload,
        },
        effets: {
          async loadData(payload, rootState) {
            const response = await fetch('http://example.com/data')
            const data = await response.json()
            this.add(data)
          }
        }
      }
      list: {}
    },
    redux: {
      reducers: {},
      middlewares: [thunk],
    },
    plugins: [loading]
  })复制代码

init

对rematch进行初始化,返回一个store对象,包含了使用redux初始化store对象的所有字段。

models: { [string]: model }

一个对象,属性的键作为rootState上的的键

model.state: any

用来初始化model

model.reducers: { [string]: (state, payload) => any }

一个对象,属性是用来改变model state的方法,第一个参数是这个model的上一个state,第二个参数是payload,函数返回model下一个state。这些方法应该是纯函数。

model.effects: { [string]: (payload, rootState) }

一个对象,异步或者非纯函数的方法放在这个对象中,可以与async/await一起使用

redux

通过这个属性,可以兼容老项目中的redux配置。

plugins

rematch是一个插件系统,通过这个字段可以配置第三方的插件。

redux流程:

redux探索:rematch

rematch流程:

redux探索:rematch

例子

##index.js
  import React from 'react'
  import ReactDOM from 'react-dom'
  import { Provider } from 'react-redux'
  import { init } from '@rematch/core'
  import App from './App'
  ​
  const count = {
    state: 0,
    reducers: {
      increment: s => s + 1,
    },
    effects: dispatch => ({
      async asyncIncrement() {
        await new Promise(resolve => {
          setTimeout(resolve, 1000)
        })
        dispatch.count.increment()
      },
    }),
  }
  ​
  const store = init({
    count,
  })
  ​
  // Use react-redux's <Provider /> and pass it the store.
  ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
    document.getElementById('root')
  )
  ​
  ​
  ##App.js
  import React from 'react'
  import { connect } from 'react-redux'
  ​
  // Make a presentational component.
  // It knows nothing about redux or rematch.
  const App = ({ count, asyncIncrement, increment }) => (
    <div>
      <h2>
        count is <b style={{ backgroundColor: '#ccc' }}>{count}</b>
      </h2>
  ​
      <h2>
        <button onClick={increment}>Increment count</button>{' '}
        <em style={{ backgroundColor: 'yellow' }}>(normal dispatch)</em>
      </h2>
  ​
      <h2>
        <button onClick={asyncIncrement}>
          Increment count (delayed 1 second)
        </button>{' '}
        <em style={{ backgroundColor: 'yellow' }}>(an async effect!!!)</em>
      </h2>
    </div>
  )
  ​
  const mapState = state => ({
    count: state.count,
  })
  ​
  const mapDispatch = dispatch => ({
    increment: dispatch.count.increment,
    asyncIncrement: dispatch.count.asyncIncrement,
  })
  ​
  // Use react-redux's connect
  export default connect(
    mapState,
    mapDispatch
  )(App)
  ​复制代码

老项目接入

主要针对已经使用thunk中间键的老项目。

1、安装依赖,并删除依赖中的redux

yarn add @rematch/core
yarn remove redux (删除redux可能会造成eslint报错)

2、修改redux入口文件

src/store/index.js
  ​
  import { init } from '@rematch/core';
  import thunk from 'redux-thunk';
  import reduxReducerConfig from '@/reducers';
  import models from '../models';
  ​
  const store = init({
    models,
    redux: {
      reducers: {
        ...reduxReducerConfig
      },
      middlewares: [thunk],
    },
  });
  ​
  export default store;复制代码

3、修改reducers的入口文件

import { routerReducer as routing } from 'react-router-redux';
  - import { combineReducers } from 'redux';
  import dispatchConfigReducer from './dispatch-config';
  import counterReducer from './count';
  ​
  - export default combineReducers({
  -   routing,
  -   dispatchConfigReducer,
  -   counterReducer,
  - });
  ​
  + export default {
  +   routing,
  +   dispatchConfigReducer,
  +   counterReducer,
  + };复制代码

4、增加model的入口文件

+ src/models
  + src/models/re-count.js
  + src/models/config-list.js
  + src/models/index.js
  ​
  index.js
  ​
  import reCount from './re-count';
  import configList from './config-list';
  ​
  export default {
    reCount,
    configList,
  };复制代码

如果老项目中没有使用redux,可以使用 yarn remove thunk 删除thunk的依赖和reducers这个文件夹,并且在init初始化的时候可以不用传redux这个配置。

如果接入rematch,需要锁定版本,rematch中引入的redux版本为4.0.0,所以老项目中的redux要更新为为4.0.0,不然打包的时候会把两个版本的redux都打进去。

新项目配置

index.js
  ​
  import React from 'react';
  import { render } from 'react-dom';
  import { browserHistory, Router } from 'react-router';
  import { syncHistoryWithStore } from 'react-router-redux';
  import { Provider } from 'react-redux';
  import routes from '@/routes';
  import store from '@/store';
  import '@/styles/index.less';
  ​
  const history = syncHistoryWithStore(browserHistory, store);
  ​
  render(
    <Provider store={store}>
      <Router history={history} routes={routes} />
    </Provider>,
    document.getElementById('root'),
  );
  ​
  ---------------------------------------------------------------------------------------
  ​
  新建store文件夹,并添加index.js
  ​
  import { init } from '@rematch/core';
  import { routerReducer as routing } from 'react-router-redux';
  import models from '../models';
  ​
  const store = init({
    models,
    redux: {
      reducers: {
        routing,
      },
    },
  });
  ​
  export default store;
  ​
  ---------------------------------------------------------------------------------------
  ​
  新建models文件夹,并添加index
  ​
  models结构
  ├── common
  │   ├── bizLineList.js
  │   └── index.js
  └── index.js复制代码

bug

Redux DevTools 要升级到最新版,2.16.0有bug

参考

重新思考Redux

Rematch: 重新设计 Redux

精读《重新思考 Redux》


以上所述就是小编给大家介绍的《redux探索:rematch》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Types and Programming Languages

Types and Programming Languages

Benjamin C. Pierce / The MIT Press / 2002-2-1 / USD 95.00

A type system is a syntactic method for automatically checking the absence of certain erroneous behaviors by classifying program phrases according to the kinds of values they compute. The study of typ......一起来看看 《Types and Programming Languages》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换