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 一.概述 机器学习算法在近几年大数据点燃的热火熏陶下已经变得被人所“熟知”,就算不懂得 ...
随机推荐
- MATLAB符号对象与符号运算
序言 符号对象(Symbolic Objects 不同于普通的数值计算)是Matlab中的一种特殊数据类型,它可以用来表示符号变量.表达式以及矩阵,利用符号对象能够在不考虑符号所对应的具体数值的情况下 ...
- Oracle 11g R2性能优化 10046 event
作为SQL Trace的扩展功能,Oracle 10046 event(10046事件)是一个重要的调试事件,也可以说是系统性能分析时最重要的一个事件,它包含比SQL Trace更多的信息.但可惜的是 ...
- java项目的异常处理
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用System.ou ...
- 31 Python中 sys.argv[]的用法简明解释(转)
Python中 sys.argv[]的用法简明解释 因为是看书自学的python,开始后不久就遇到了这个引入的模块函数,且一直在IDLE上编辑了后运行,试图从结果发现它的用途,然而结果一直都是没结果, ...
- C# Winform设计运行时,界面模糊
程序在Visual Studio设计的很清晰的菜单和界面,运行的时候菜单和控件上字体变得很模糊,界面大小也发生了变化 解决方法是:更改程序的配置文件,使程序运行时自动检测屏幕分辨率,在高分屏时禁用系统 ...
- final关键字的几种用法
在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构.下面我们来了解一下final ...
- VScode中运行python程序,使用Code Runner插件
把我的py文件加载在里面,想要运行一下. 可是...没有动静 于是我又到网上去查,原来要配置tasks.json,可我照着网上的方法弄好后还是没法运行,于是我便投入了code runner的怀抱 co ...
- 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165316
2018-2019-2 <网络对抗技术>Exp0 Kali安装 Week1 20165316 下载 我分别下载了kali-linux-2019.1-i386的镜像文件和kali-linux ...
- npm install --save 、--save-dev 、-D、-S 的区别
备注:<=> 意为等价于: 1.npm install <=> npm i --save <=> -S --save-dev <=> -D npm ...
- 2.2JAVA基础复习——JAVA语言的基础组成运算符和语句
JAVA语言的基础组成有: 1.关键字:被赋予特殊含义的单词. 2.标识符:用来标识的符号. 3.注释:用来注释说明程序的文字. 4.常量和变量:内存存储区域的表示. 5.运算符:程序中用来运算的符号 ...