前言:

前段时间学习完react后,刚好就接到公司一个react项目的迭代,顺便巩固一下前段时间的学习成果。项目使用的是redux+react-router,将所有的数据都放在redux中,异步处理数据使用redux-saga。由于是迭代项目,所以代码风格还是沿用之前项目的写法,将所有的数据都放在redux中。写redux的时候心中默默的吐槽了无数次,特别是每次从服务端异步获取数据的时候心中都会默默的想 “我只是想实现从服务端取一个列表数据,然后保存在store中,为什么需要引入redux-saga,并且引入后写法还是很繁琐(虽然流程很清晰明了,但是需要进行大量的复制粘贴)” ,写着写着感觉心态就快崩了 。后面经过同事的介绍,了解到有rematch这么一个更好用的js状态容器,终于可以脱离redux了。

简介:

先看看rematch的官方介绍:

Rematch是没有boilerplate的Redux最佳实践。没有多余的action types,action creators,switch 语句或者thunks。

rematch是在redux的基础上再次封装后成果,在rematch中我们不用声明action类型、action创建函数、thuks、store配置、mapDispatchToProps、saga。如果你习惯使用vuex,那么你一定会喜欢上rematch的,因为rematch的写法和vuex基本一样。

一个简单的demo:

先看看我们的项目结构:

├── index.html
├── index.js        # 项目的入口
├── ....
└── store
├── index.js # 引入modules的各个模块,初始化store的地方
└── modules
├── count.js # count模块
└── info.js    # info模块

1. store/index.js,初始化一个store实例

import { init } from '@rematch/core';
import count from './modules/count';
import info from './modules/info'; const store = init({
models: {
count,
info,
}
}) export default store;

   rematch提供 init()方法,返回一个store的实例。初始化store的时候rematch支持传入多个模块,在中、大型项目中可以根据业务的需要,拆分成多个模块,这样项目的结果就会变得清晰明了。

2. store/modules/count.js,编写count模块业务代码

const count = {
state: {
num: 1,
     type: 2
},
reducers: {
increment(state, num1, num2) { // 从第二个变量开始为调用increment时传递进来的参数,后面依次类推,例如:dispatch.count.increment(10, 20)时, num1 = 10 , num2 = 20.
return {
          ...state,
num: num1
}
},
},
effects: {
async incrementAsync(num1, rootState, num2) { // 第二个变量为当前model的state的值,num1为调用incrementAsync时传递进来的第一个参数,num2为调用时传递的第二个参数,后面依次类推。例如:dispatch.count.incrementAsync(10, 20)时,num1 = 10, num2 = 20
await new Promise(resolve => setTimeout(resolve, 2000));
this.increment(num1);
}
}
} export default count;

  事实上我们的count模块就是一个对象,该对象包含三个属性:state、reducers、effects。

  state:存放模块状态的地方。

  reducers:改变store状态的地方,每个reducers函数都会返回一个对象作为模块最新的state。reducers中的函数必须为同步函数,如果要异步处理数据需要在effects中处理。注意:只能通过在reducers的函数中通过返回一个新的对象来改变模块中state的值,直接通过修改state的方式是是不能改变模块的state的值。例:

        increment(state, num1) {
state.num = num1 // 这样的写法是错误的
},

  effects:处理异步数据的地方,比如:异步从服务端获取数据。注意:在effects中是不能修改模块的state,需要在异步处理完数据后调用reducers中的函数修改模块的state。

  rematch的state、reducers、effects和vuex的state、mutaition、action用法非常相似,在vuex中mutation修改model的state的值,action进行异步处理数据。

 3. 在组件中获取state和修改state的值

  有2种方法可以获取state和修改state:(1)使用redux的高阶组件connect将state、reducers、effects绑定到组件的props上。(2)使用rematch提供的dispatch和getState。

  (1)使用redux的高阶组件connect

    使用redux提供的高阶组件connect给App组件注册countState和countDispatch属性,其中countState对应的是count模块的state属性,countDispatch对应的是count模块的reducers和effects。在组件中使用this.props.countState和this.props.countDispatch就可以访问到count模块提供的state和reducers、effects了。

import React, {Component} from 'react';
import {connect} from 'react-redux'; class App extends Component {
handleClick = () => {
const { countDispatch } = this.props;
countDispatch.increment(10)
}; render() {
const { countState } = this.props;
return (
<div className="App" onClick={this.handleClick}>
当前num为{countState.num},点我num加10
</div>
);
};
} const mapStateToProps = (state) => ({
countState: state.count
}) const mapDispatchToProps = (dispatch) => ({
countDispatch: dispatch.count
}) export default connect(mapStateToProps, mapDispatchToProps)(App);

  (2)dispatch和getState

    getState:rematch提供的getState方法返回整个store的state对象,如果要单独访问count模块的state,只需要 getState( ).count即可。

    dispatch:rematch提供的dispatch可以直接调用整个store中定义的reducers和effects。例:dispatch.count.increment(10) ,其中count为store中的一个model,increment方法为count模块中提供的一个reducers。调用effects的方法和调用reducers的方法一样。

import React, {Component} from 'react';
import { dispatch, getState } from '@rematch/core'; class App extends Component {
handleClick = () => {
     console.log(getState().count); // {num: 1, a: 1}
dispatch.count.increment(10)
}; render() {
let countState = getState().count;
console.log(countState);
return (
<div className="App" onClick={this.handleClick}>
当前num为{countState.num},点我num加10
</div>
);
};
}
const mapStateToProps = (state) => ({
countState: state.count
}) const mapDispatchToProps = (dispatch) => ({
countDispatch: dispatch.count
}) export default connect(mapStateToProps, mapDispatchToProps)(App);
 

    

4、在一个model的reducers中的函数中触发另外一个model的reducers中的函数  

  场景:A函数和B函数里面有大量相似的代码,这个时候我们一般的做法都是将A、B函数的公共部分提取出来成一个公共函数,这样我们就不需要在A函数和B函数中写大量相似的代码。假如在reducers中,我们将A函数和B函数提取的公共函数C放在公共模块info的reducers中,A函数是在count模块的reducers中。在这种情况下我们就需要在公共模块info的函数C执行完后调用count模块的A函数。

{  // count模块
...
reducers: {
...
'info/addAge': (state, payload) => { // payLoad的值为addAge传入的值10
console.log(payload) // 10
return {
...state,
num: 10
}
}
},
...
} { // info模块
...
reducers: {
addAge(state, num) {
return {
age: state.age + num.age,
}
}
}
...
}

  通过dispatch.info.addAge(10)调用info模块的addAge函数,当addAge函数执行完后会触发count模块的 ' info/addAge ' ,并且 ' info/addAge '的参数payload的值为调用info模块的addAge函数时传入的参数 10

总结:

由于rematch的写法和vuex很相似,所以在接触rematch的时候觉得非常熟悉,很好上手,具体有有哪些坑只有等下次项目中引入了rematch踩了才知道。

rematch:当你受不了redux繁琐写法的时候,是时候了解一波rematch了的更多相关文章

  1. Rematch Redux的替代品

    前言:Rematch和vuex很像. 文档:https://github.com/yurizhang/rematch 简介: 先看看rematch的官方介绍: Rematch是没有boilerplat ...

  2. React进阶篇(2) -- Redux

    前言 如果还不知道为什么要使用Redux,说明你暂时还不需要它. 三大原则 单一数据源 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一 ...

  3. redux-simple 简化版的redux

    作为react的粉丝,当然要吐槽一下react组件通信问题.react的单向数据流是组件通信的一大阻碍,只允许父组件向子组件传值,子组件向父组件传值只能通过父组件向子组件传递回调函数实现.如果在深层次 ...

  4. listview--Java泛型应用之打造Android万能ViewHolder-超简洁写法

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010785585/article/details/52808656 转载请注明出处:http:// ...

  5. redux基础(1)

    redux ps:每个案例都是接着上一个案例写的 主要以案例讲解如何使用,具体概念请参考如下: 基本概念参考1 基本概念参考2 案例源码戳这里 一.Store.Action.Reducer简介 Sto ...

  6. rematch的基本用法

    rematch是对redux的二次封装,简化了redux是使用,极大的提高了开发体验.rematch仅仅是对redux的封装,没有依赖redux-saga,也没有关联react,因此其可以用在其他的视 ...

  7. 【React】Stateless Function

    React创建组件的时候,有3种写法: // 1. 传统写法 const App = React.createClass({}); // 2. es6 的写法 class App extends Re ...

  8. KnockoutJS 3.X API 第六章 组件(4) 自定义元素

    自定义元素提供了一种将组件注入视图的方便方法. 本节目录 介绍 例子 传递参数 父组件和子组件之间的通信 传递监控属性的表达式 将标记传递到组件中 控制自定义元素标记名称 注册自定义元素 备注1:将自 ...

  9. Python机器学习库scikit-learn实践

    原文:http://blog.csdn.net/zouxy09/article/details/48903179 一.概述 机器学习算法在近几年大数据点燃的热火熏陶下已经变得被人所“熟知”,就算不懂得 ...

随机推荐

  1. Module 3 - Azure - Web Apps

     Module 3 - 微软云 Azure - Web Apps 1. Create new Web application in the Azure Portal Azure Portal -> ...

  2. 18. C# 转换

    1.重载转换运算符 到目前为止,我们使用的类型转换,包括隐式类型转换和显示类型转换都是在两个相关的类中进行的,这几个类要么是简单类型之间的转换,比如int 隐式转换成double,要么是有继承关系,或 ...

  3. PHP----------一群猴子排成一圈,按1,2,...,n依次编号。

    1.一群猴子排成一圈,按1,2,...,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去...,如此不停的进行下去, 直到最后只剩下一只猴子为止,那 ...

  4. arcgis 画图工具

    arcgis 4.x系列JavaScript API在4.4及以前的版本对画图工具(Draw)是不支持的,自4.5版本后才提供Draw的类.相关连接:https://developers.arcgis ...

  5. Go 初体验 - 错误与异常处理 - recover和panic

    先看代码: 输出: 内建函数panic可以让我们人为地产生一个运行时恐慌.不过,这种致命错误是可以被恢复的.在Go语言中,内建函数recover就可以做到这一点. 实际上,内建函数panic和reco ...

  6. office2007每次打开都要配置文件,怎么取消配置

    有时候 Office2007打开文档,每次都提示需要安装.配置,配置完成之后,下次打开又需要配置点击取消就不能打开.非常的烦.ffice2007下载后为什么每次打开总需要置?office2007每次打 ...

  7. Raize 重新编译

    最近项目用到了Raize5的日历控件, 需要在中文版本与英文版本中切换显示, 这个需要修改 RzPopups.pas, 修改了需要重新编译. 费老大劲了.   首选修改 RzBorder.pas, 不 ...

  8. IT题库1-HashMap、HashSet和HashTable(区别?数据格式?)

    1. HashTable和HashMap的区别 HashMap和Hashtable都实现了Map接口.主要区别:线程安全性,同步(synchronization),以及速度. 1.HashMap是非s ...

  9. 零门槛,包教会。让你在5分钟内使用以太坊ERC20智能合约发行属于自己的空气币

    前言 目前区块链是互联网中最最火的风口,没有之一.我周围的很多朋友也加入了“炒币”行列,但很不幸,几乎都被“割韭菜”了.而经过我的几天研究,发现,如果自己要发行一种空气币,简直太简单了.只需要下面几个 ...

  10. platform怎么实现数据数据和驱动分离

    一些重要的结构体: struct platform_device { const char * name; int id; struct device dev; u32 num_resources; ...