揭开redux,react-redux的神秘面纱
16年开始使用react-redux,迄今也已两年多。这时候再来阅读和读懂redux/react-redux源码,虽已没有当初的新鲜感,但依然觉得略有收获。把要点简单写下来,一方面供感兴趣的读者参考,另一方面也是自己做下总结。
为了完整阅读体验,欢迎移步到我的博客原文。
redux
react-redux最核心的内容就是redux。内带redux,react-redux只提供了几个API来关联redux与react的组件以及react state的更新。
首先,看下如何使用redux。 redux老司机可以直接滑动滚轮至下一章。
简单来说,redux有三个概念,action, reducer 和 dispatch。 action和dispatch比较好理解:动作指令和提交动作指令方法。而reducer,个人在字面上没有理解,但抽象层面上可以理解为用来生成state的函数。用一个简单案例体现这三个概念:
// action
const INCREMENT = { type: 'INCREMENT' }
// reducer
function count( state = 0, action ) {
switch( action.type ) {
case 'INCREMENT':
return state + 1
default:
return state
}
}
// dispatch
// 此处开始使用redux
const store = redux.createStore( count )
console.log( store.getState() ) // 0
store.dispatch( INCREMENT )
console.log( store.getState() ) // 1
接下来说说redux中的两大模块:
store对象- 中间件
store对象
APIcreateStore会创建了一个store对象,创建的过程中它主要做了下面两件事:
- 初始化state
- 暴露相关接口:
getState(),dispatch( action ),subscribe( listener )等。其中getState()用来获取store中的实时state,dispatch(action)根据传入的action更新state,subscribe( listener)可以监听state的变化。
中间件
中间件可以用来debug或提交异步动作指令. 在初始化store的时候,我们通过createStore( reducer, state, applyMiddleware( middleware1, middleware2 ) )添加多个中间件。
为了实现多个中间件,redux专门引入了函数式编程的compose()方法,简单来说,compose将多层函数调用的写法变得优雅:
// 未使用compose方法
a( b( c( 'd' ) ) )
// 用compose方法
compose( a, b, c )('d')
而中间件的写法比较奇特,是多级函数,在阅读源码的时候有点绕。显然中间件的写法还可以优化,尽管现在的写法方便在源码中使用,但对redux用户来说稍显复杂,可以用单层函数。
function logMiddleware({ getState }) {
return nextDispatch => action => {
console.log( 'before dispatch', getState() )
const res = nextDispatch( action )
console.log( 'after dispatch', getState() )
return res
}
}
react-redux
了解了redux运作原理,就可以知道react-redux的大部分使用场景是如何运作。react-redux提供了几个API将redux与react相互关联。
基于上一个案例展示react-redux的用法:
// action
const increment = () => ({ type: 'INCREMENT' })
// reducer
function count( state = 0, action ) {
switch( action.type ) {
case 'INCREMENT':
return state + 1
default:
return state
}
}
// redux
const store = Redux.createStore( count )
// react-redux
const { Provider, connect } = ReactRedux
const mapStateToProps = state => ( { count: state } )
const mapDispatchToProps = dispatch => ( { increment : () => dispatch( increment() ) } )
const App = connect( mapStateToProps, mapDispatchToProps )( class extends React.Component {
onClick = () => {
this.props.increment()
}
render() {
return <div>
<p>Count: { this.props.count }</p>
<button onClick={ this.onClick }>+</button>
</div>
}
} )
ReactDOM.render( <Provider store={ store }>
<App />
</Provider>, document.getElementById( 'app' ) )
react-redux提供最常用的两个API是:
Providerconnect
Provider
Provider本质上是一个react组件,通过react的context api(使一个组件可以跨多级组件传递props)挂载redux store中的state,并且当组件初始化后开始监听state。
当监听到state改变,Provider会重新setState在context上的storeState,简要实现代码如下:
class Provider extends Component {
constructor(props) {
super(props)
const { store } = props
this.state = {
storeState: Redux.store.getState(),
}
}
componentDidMount() {
this.subscribe()
}
subscribe() {
const { store } = this.props
store.subscribe(() => {
const newStoreState = store.getState()
this.setState(providerState => {
return { storeState: newStoreState }
})
})
}
render() {
const Context = React.createContext(null)
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
}
}
connect()
connect方法通过connectHOC(HOC: react高阶组件)将部分或所有state以及提交动作指令方法赋值给react组件的props。
小结
写react不用redux就像写代码不用git, 我们需要用redux来更好地管理react应用中的state。了解redux/react-redux的运作原理会消除我们在使用redux开发时的未知和疑惑,并且在脑中有一个完整的代码执行回路,让开发流程变得透明,直观。
如果本文帮助到了你,我也十分荣幸, 欢迎点赞和收藏。如果有任何疑问或者建议,都欢迎在下方评论区提出。
揭开redux,react-redux的神秘面纱的更多相关文章
- 揭开Sass和Compass的神秘面纱
揭开Sass和Compass的神秘面纱 可能之前你像我一样,对Sass和Compass毫无所知,好一点儿的可能知道它们是用来作为CSS预处理的.那么,今天请跟我一起学习下Sass和Compass的一些 ...
- 揭开.NET消息循环的神秘面纱(GetMessage()无法取得任何消息,就会进入Idle(空闲)状态,进入睡眠状态(而不是Busy Waiting)。当消息队列不再为空的时候,程序会自动醒过来)
揭开.NET消息循环的神秘面纱(-) http://hi.baidu.com/sakiwer/item/f17dc33274a04df2a9842866 曾经在Win32平台下奋战的程序员们想必记得, ...
- 揭开DRF序列化技术的神秘面纱
在RESTful API中,接口返回的是JSON,JSON的内容对应的是数据库中的数据,DRF是通过序列化(Serialization)的技术,把数据模型转换为JSON的,反之,叫做反序列化(dese ...
- 揭开Vue异步组件的神秘面纱
简介 在大型应用里,有些组件可能一开始并不显示,只有在特定条件下才会渲染,那么这种情况下该组件的资源其实不需要一开始就加载,完全可以在需要的时候再去请求,这也可以减少页面首次加载的资源体积,要在Vue ...
- Immutable.js 以及在 react+redux 项目中的实践
来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...
- RxJS + Redux + React = Amazing!(译一)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: https:/ ...
- RxJS + Redux + React = Amazing!(译二)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- react+redux教程(六)redux服务端渲染流程
今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...
随机推荐
- vs文件属性(复制到输出目录)是什么意思
右击项目里的文件,选择属性(F4)会有复制到输出目录的选项. 它提供三项选择,如图: 如果选择始终复制或如果较新则复制会在该程序集的bin目录下生成该文件,如图:
- Base class for cloning an object in C#
Base class for cloning an object in C# /// <summary> /// BaseObject class is an abstract class ...
- 希尔排序——Java实现
一.排序思想 希尔排序(Shell’s Sort)是插入排序的一种,是直接插入排序算法的一种更高版本的改进版本. 把记录按步长gap分组,对每组记录采用直接插入排序方法进行排序: 随着步长逐渐减小,所 ...
- Redis过期设置
Redis支持按key设置过期时间,过期后值将被删除(在客户端看来是补删除了的) 用TTL命令可以获取某个key值的过期时间(-1表示永不过期) 127.0.0.1:6379> set name ...
- easyui-textbox 绑定事件
$('#Id').textbox({ inputEvents: $.extend({},$.fn.textbox.defaults.inputEvents,{ keyup:function(event ...
- Spring Cloud Ribbon负载均衡配置类放在Spring boot主类同级增加Exclude过滤后报Field config in com.cloud.web.controller.RibbonConfiguration required a bean of type 'com.netflix.client.config.IClientConfig' that could not b
环境: Spring Cloud:Finchley.M8 Spring Boot:2.0.0.RELEASE 目录结构: 可以看到代码第13行的注释,我已经在@ComponentScan注解中添加了E ...
- vue的拖拽文件
<div ref='select_frame' ondragstart="return false">//防止跳转 </div> this.$refs.se ...
- Centos7设置文件夹写入权限
用 root 账号执行chmod命令: #chmod -R 777 dirPath 参数 -R 表示递归,dirPath及其之内的所有文件夹.文件都被改变了权限. 例子: #chmod -R 777 ...
- pl/sql 存储过程执行execute immediate 卡住
在存储过程中,执行了create table.update table.insert into table 但是在使用pl/sql的存储过程调试的时候,一有问题就直接卡住(标识:执行中.....) 后 ...
- 2017软件测试_HW1_最近遇到的编程问题
最近遇到的错误:我对着网页源代码编写了一段爬虫语句,运行没有提示有错误,而且 可以抓取到全部的数据,但是不能按照要求将这些数据分到制定的位置. 发现问题原因:我把抓取到的字段对着网页源码看了一下,发 ...