简化React中的Action的写法,不要中间件,不写dispatch
我们在写React应用时,通常用到redux做状态管理,然后会用到一些中间件来支持异步action,比如redux-thunk.通常我们的代码类似下面这样的:
//ActionType R.js
export ActionType{
TYPE1:'type1',
TYPE2:'type2',
TYPE3:'type3',
// others
}
//reducer reducer.js
import {ActionType as AT} from 'R'
export default function(state={},action){
switch(action.type){
case AT.TYPE1:
return {
...state,
...action.data,
// or other
}
case AT.TYPE2:
//...
default:
return state
}
}
//Action Action.js
import {ActionType as AT} from 'R'
const act = {
action1:data=>dispatch=>{
// some action such as ajax
dispatch({
type:AT.TYPE1,
data:{
// data
}
})
}
action2:()=>(dispatch,getState)=>{
// call another action
dispatch(act.action3())
}
action3:()=>()=>{
// even you never use the dispath or getState,you still have to code like this.
}
}
export default act
// Component
@connect(
state=>state.reducer1,
dispatch=>bindActionCreators(Action,dispatch)
)
export default class View extends React.Component{
doAction1(){
this.props.action1({})
}
render(){
return(
<div>
anything else
</div>
)
}
}
功能很简单,却需要些这么多actionType, reducer里面还有那么多case分支。而最烦的是action,直觉上我们是希望能够写普通的function,而不用强行写上dispatch和getState, 一个action调用另一个action竟然也不能直接调用。虽然我们知道是需要这样做,需要用actionType来区分action,reducer里面也需要根据type来做相应的更新,action中也需要dispatch来发出action。
但如果我们就是不想写的这么麻烦,能有什么办法吗?
答案之一是用mobx之类的工具来管理状态。当然,本文要介绍的是在redux中的方法,ev-redux. 先来看看使用后的效果:
首先安装:npm i --save ev-redux
然后你的代码差不多是这样:
// init evStore in you app.js when create store.
import {evStore} from 'ev-redux'
const store = createStore(...)
evStore.init(store)
// redux/reducer.js
import {ActionType as TYPE} from './index.js'
const initState={}
export default function(state=initState,action){
if(action.type === TYPE){
return {
...state,
...action.data
}
}
return state
}
// redux/Action.js
import {evRedux} from 'ev-redux'
@evRedux
export default class Action{
constructor(actionType){
this.actionType = actionType
}
action1(x){
this.update({
x
})
}
action2(){
this.dispatch({
type:this.actionType,
data:{y:this.getState().reducer2.y+1}
})
// to call another action, just call no need dispath!
this.action3({z:3})
// or just update
// this.update({y:this.getState().reducer2.y+1})
}
action3(z){
setTimeout(()=>{
this.update({z})
},1000)
}
}
// redux/index.js
import Action from './Action'
import reducer from './reducer'
import {connect as conn} from 'react-redux'
const connect = view => conn(state=>state.reducer2)(view)
const ActionType = Symbol()
const action = new Action(ActionType)
export {reducer,ActionType,action,connect}
// Component
import action from './action'
@connect
export default class View extends React.Component{
doAction1(){
// just call an action as we call a function.
action.action1()
}
render(){
return(
<div>
anything else
</div>
)
}
}
不要只看着代码并没有减少。仔细看看 reducer和action部分,这样的action,这样的reducer你还不愿意用嘛?
- 不需要中间件来支持异步任务。
- 不需要去写那么多actionTypes,一个reducer对应一个action就行,使用symbol保证不重复。
- reducer中不需要那么多case分支,只需要合并一下action传过来的state和原来的state就可以。
- 重点是action,不需要手动在每个方法上加上dispatch和getState.你只需要在需要更新store时,构造好需要更新的那部分state,,然后调用update就行,type都不需要带。update哪儿来的?你直接用就行,后面会说。如果你想要用dispath和getState,直接从上下文取就行,this.dispatch,this.getState随便用。调用其他action,直接用this调用就ok,就像调用普通方法那样调用。
ok了,用法介绍完了。具体的原理简单说明一下:
首先我们要触发reducer来更新store,就要用到dispatch来分发action。我们的update方法里面就是这么做的。之所以把构造要更新的state方法action, 而不是在reducer中通过不同的type来区分,是因为我觉得对于每个action,里需要更新那部分state,在action里面你是最清楚的。如果你在actino里面只是dispatch一个action,然后去reducer中构造state结构并更新,你不仅要写很多个多余的actionType,而且可能还要回头看这个type是哪个action触发的,还要回想这个action里面传过来的data是什么样的,明显比在action中构造要复杂。
至于为什么action中我们明明没写update,却可以直接用,其实在easy-redux中,我们对action做了代理。在初始或easyStore时,我们能够获取到dispatch和getState,然后在action的get方法中,我们用反射来set update、dispatch、getState. 这样在我们的action中就能够直接在上下文中调用到它们了。
原理就是用到js里面的代理和反射,代码也很简单,这里就不展开说明了,直接放上github地址:https://github.com/evolify/EvRedux
原文发布时间为:2018年01月30日
原文作者:孤丶狼丶
本文来源:开源中国 如需转载请联系原作者

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
DNS服务-了解篇
简介 DNS是用来名字解析的,名字解析成IP地址,IP地址解析成名字,正反操作,有服务器端和客户端即 S/C DNS是应用层协议,基于UDP/53、TCP/53端口,缺一不可 分为正向解析和反向解析/递归查询、迭代查询 注意:正反向解析是两个不同的名称空间,是两棵不同的解析树 名称解析:主机名解析 把一种名称转换为另一种名称的过程 根据用户提供的名称,去查询解析库,以得到另一种名称 hosts:文本文件 用户自定义了对应的解析列表即要解析的FQDN与IP地址对应关系 有时候hosts很好的解决了DNS服务器访问不了的情况 如:某个域所在的权威DNS服务器出问题了,网站图片不显示等,这时候在hosts文本里写上对应的FQDN和IP地址就可。 备注:FQDN也就是我们所说的网址,如www.xxx.com 如果在本机定义了hosts文本则优先本列表,本列表没有再去DNS库查询 递归查询 用户向第一个DNS服务发请求,DNS收到后,如果它这有直接的结果就直接给你,如果没有就会向根DNS服务询问,层层询问直到问道结果返回给你,负责到底 迭代查询 上述过程中去问根,根给你推荐别人,你去问它,...
-
下一篇
又是一年419,云上云下话等保
“419”,我们来谈谈“云上云下信息安全”这件事,应时应景。2016年4月19日,网络安全和信息化工作座谈会召开。这是我国网络安全和信息化领域具有重要历史意 2016年4月19日,网络安全和信息化工作座谈会召开。这是我国网络安全和信息化领域具有重要历史意义和战略影响的大事件。 2017年6月1日,《中华人民共和国网络安全法》开始施行。保障网络安全,维护网络空间主权和国家安全、社会公共利益,保护公民、法人和其他组织的合法权益,促进经济社会信息化健康发展成为一项最核心的工作。 2018年5月25日,号称史上最严厉的数据保护条例——欧盟《一般数据保护条例》(GDPR)将正式施行,数据隐私保护、合规等问题再次被推向风口浪尖。 虽然大家都心知肚明,云安全并不完全是一个技术问题,更多可能是“心理”问题,但不可否认,安全仍然是企业上云的一个重要挑战,或者说是难点。 01安全等级保护是一项国家制度 4月14日,国内首家案例式科技沙龙Q.Club的第一期活动,就将活动主题定为“走进云上云下信息安全时代”。虽然会议举行当天是周六,而且有大风,但是仍然不能阻挡沙龙参与者的热情。来自中国电子技术标准化研究院、...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL数据库在高并发下的优化方案
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Hadoop3单机部署,实现最简伪集群