rematch:当你受不了redux繁琐写法的时候,是时候了解一波rematch了
前言:
前段时间学习完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了的更多相关文章
- Rematch Redux的替代品
前言:Rematch和vuex很像. 文档:https://github.com/yurizhang/rematch 简介: 先看看rematch的官方介绍: Rematch是没有boilerplat ...
- React进阶篇(2) -- Redux
前言 如果还不知道为什么要使用Redux,说明你暂时还不需要它. 三大原则 单一数据源 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一 ...
- redux-simple 简化版的redux
作为react的粉丝,当然要吐槽一下react组件通信问题.react的单向数据流是组件通信的一大阻碍,只允许父组件向子组件传值,子组件向父组件传值只能通过父组件向子组件传递回调函数实现.如果在深层次 ...
- listview--Java泛型应用之打造Android万能ViewHolder-超简洁写法
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010785585/article/details/52808656 转载请注明出处:http:// ...
- redux基础(1)
redux ps:每个案例都是接着上一个案例写的 主要以案例讲解如何使用,具体概念请参考如下: 基本概念参考1 基本概念参考2 案例源码戳这里 一.Store.Action.Reducer简介 Sto ...
- rematch的基本用法
rematch是对redux的二次封装,简化了redux是使用,极大的提高了开发体验.rematch仅仅是对redux的封装,没有依赖redux-saga,也没有关联react,因此其可以用在其他的视 ...
- 【React】Stateless Function
React创建组件的时候,有3种写法: // 1. 传统写法 const App = React.createClass({}); // 2. es6 的写法 class App extends Re ...
- KnockoutJS 3.X API 第六章 组件(4) 自定义元素
自定义元素提供了一种将组件注入视图的方便方法. 本节目录 介绍 例子 传递参数 父组件和子组件之间的通信 传递监控属性的表达式 将标记传递到组件中 控制自定义元素标记名称 注册自定义元素 备注1:将自 ...
- Python机器学习库scikit-learn实践
原文:http://blog.csdn.net/zouxy09/article/details/48903179 一.概述 机器学习算法在近几年大数据点燃的热火熏陶下已经变得被人所“熟知”,就算不懂得 ...
随机推荐
- C语言--关于第0次作业
你对网络专业或者计算机专业了解是怎样? 答:我认为网络专业或者计算机专业是网络管理.软件开发.程序设计等一些高等企业就业的基础知识.以及涉及到环境开发等的专业领域.知道它很难,但是社会对它的需求很高. ...
- MATLAB 通过对话框返回值选择下一步操作
学习来源:http://muchong.com/t-10428977-1-pid-1 Userchoice = questdlg(['您确定导入彩色图像?'],'提示','转为灰度图处理','展示彩色 ...
- java中进程与线程的区别
进程是一个正在运行的应用程序.一个进程包含一个或多个线程.它可以是一段完整的代码或部分程序的动态执行.系统资源分配与调度的基本单位.而线程是CPU调度与运行的基本单位,它是一组指令的集合或是程序的特殊 ...
- puppeteer(四)常见问题——部分元素无法操作,代码没任何问题。
前言 最近写了一个小例子,但是一个page.click无论如何也不能正常操作,语法这么简单不可能有错.于是找原因,浏览器的问题吗?各种开发环境切换,nodejs版本换到较老的版本,npm版本切换,最后 ...
- asp.net 去掉小数点后面多余的0,本身为0则不显示
很多时候,比如gridview内,不想现实从数据库带出的多余小数 ,比如 4.01000 ,可显示为 4.01 如果是 0.00000, 则显示为空白 /// <summary> /// ...
- 【Linux】Jenkins安装(二)
Jenkins介绍 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1.持续的软件版本发布/测试项目. 2.监控外部调用执行的工作. 安装环境 操作系统:lin ...
- 【论文速读】Shitala Prasad_ECCV2018】Using Object Information for Spotting Text
Shitala Prasad_ECCV2018]Using Object Information for Spotting Text 作者和代码 关键词 文字检测.水平文本.FasterRCNN.xy ...
- 2018-2019-2 20175205实验一《Java开发环境的熟悉》实验报告
2018-2019-20175205实验一<Java开发环境的熟悉>实验报告 实验步骤 (一)命令行下Java程序开发 在Linux下运行结果: 在IDEA中运行结果: (二)IDEA下J ...
- JDBC中常用的接口
JDBC常用的接口DriverManager 驱动管理器获得数据库链接 Connection 数据库链接接口 Statement 语句接口,用来静态操作SQL语句 PreparedStatement ...
- 初步了解,vue的转发机制(proxyTable)
vue的转发机制(proxyTable),proxyTable代理功能可以实现转发机制,需要修改config里面修改index.js文件 修改index.vue中请求的代码(该功能是webpack-s ...