Redux 和 Redux thunk 理解
1: state 就像 model
{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
2: action, 普通的 javascript 对象, 用来描述发生了什么, 里面除了type 必须的, 还会其它属性值来改变 state。
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
3. 为了把 action 和 state 串起来, 就是 reducer, 例如下面:
reducer 一定是对应于 action 里的 type 的值, 而做变化。
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }]);
default:
return state;
}
}
Redux thunk 到底是怎么起作用的呢, 请看下面的代码:
const store = createStore(reducer, preloadedState, applyMiddleware(thunk));
当执行这个代码的时候, 实际执行了 applyMiddleware(thunk)(createStore)(reducer, preloadedState),
这个会返回一个新的 store对象, 这个 store对象的dispatch 发生了变化。
源码里首先定义原来的 store = createStore(reducer, preloadedState);
然后 thunk 里面传递下面的对象:
{
getState: store.getState,
dispatch: (action) => dispatch(action)
}
再传入原来的 store.dispatch(就是next),
返回的函数就是新的 dispatch方法:
action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
}
所以当你执行, 下面的方法判断 action 是否是函数,
dispatch( incrementAsync() );
注意下面标红的 dispatch 跟 store.dispatch 一样,所以又重新执行了1遍 dispatch = compose(...chain)(store.dispatch);
但是这个时候的 action 已经是 increment(), 不是函数了, 所以直接走到 next(action) 里面了。
function incrementAsync(delay = 1000) {
return dispatch => {
setTimeout(() => {
dispatch(increment());
}, delay);
};
}
Redux thunk 官网源码
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
//注意这里 dispatch 不用 next?
return action(dispatch, getState, extraArgument);
}
// 注意这里 next 不用 dispatch
return next(action);
};
} const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware; export default thunk;
applyMiddleware 源码如下:
import compose from './compose' // 这货的作用其实就是 compose(f, g, h)(action) => f(g(h(action))) export default function applyMiddleware(...middlewares) { return function(createStore) { return function(reducer, preloadedState, enhancer) { // 用原 createStore 先生成一个 store,其包含 getState / dispatch / subscribe / replaceReducer 四个 API
var store = createStore(reducer, preloadedState, enhancer) var dispatch = store.dispatch // 指向原 dispatch
var chain = [] // 存储中间件的数组 // 提供给中间件的 API(其实都是 store 的 API)
var middlewareAPI = {
getState: store.getState,
// 注意这里面的 dispatch 已经变成下面的 dispatch 了
dispatch: (action) => dispatch(action)
} chain = middlewares.map(middleware => middleware(middlewareAPI)) // 用原来的 store.dispatch 进行窜连
dispatch = compose(...chain)(store.dispatch) return {
...store, // store 的 API 中保留 getState / subsribe / replaceReducer
dispatch // 新 dispatch 覆盖原 dispatch,往后调用 dispatch 就会触发 chain 内的中间件链式串联执行
}
}
}
}
Redux 和 Redux thunk 理解的更多相关文章
- React-安装和配置redux调试工具Redux DevTools
chrome扩展程序里搜索Redux DevTools进行安装 新建store的时候,进行如下配置. import { createStore, applyMiddleware ,compose} f ...
- 25.redux回顾,redux中的action函数异步
回顾:Redux: 类似于 Vuex 概念:store/reducer/action action:动作 {type,.....} 一定要有type 其他属性不做限制 reducer:通过计算产生st ...
- 手把手教你撸一套Redux(Redux源码解读)
Redux 版本:3.7.2 Redux 是 JavaScript 状态容器,提供可预测化的状态管理. 说白了Redux就是一个数据存储工具,所以数据基础模型有get方法,set方法以及数据改变后通知 ...
- 记一次修改框架源码的经历,修改redux使得redux 可以一次处理多个action,并且只发出一次订阅消息
redux是一个数据状态管理的js框架,redux把行为抽象成一个对象,把状态抽象成一个很大的数据结构,每次用户或者其他什么方式需要改变页面都可以理解成对数据状态的改变,根据出发这次改变的不同从而有各 ...
- [Redux] Understand Redux Higher Order Reducers
Higher Order Reducers are simple reducer factories, that take a reducer as an argument and return a ...
- [Redux] Filtering Redux State with React Router Params
We will learn how adding React Router shifts the balance of responsibilities, and how the components ...
- 理解Redux以及如何在项目中的使用
今天我们来聊聊Redux,这篇文章是一个进阶的文章,建议大家先对redux的基础有一定的了解,在这里给大家推荐一下阮一峰老师的文章: http://www.ruanyifeng.com/blog/20 ...
- Redux 中间件的执行顺序理解
Redux.applyMiddleware(thunk, middleware1) 和 Redux.applyMiddleware(middleware1, thunk) 的区别: <!DOCT ...
- 【React】360- 完全理解 redux(从零实现一个 redux)
点击上方"前端自习课"关注,学习起来~ 前言 记得开始接触 react 技术栈的时候,最难理解的地方就是 redux.全是新名词:reducer.store.dispatch.mi ...
随机推荐
- 【usaco-Liars and Truth Tellers, 2013 Jan真假奶牛】并查集
题解: 原先我看错题了,以为是任意选择k个使得它们不矛盾. 这样的话怎么做呢?我想M^2判断,把它们分成若干个集合,集合里面两两不矛盾这个集合里所有的话就不矛盾了. 但是这样是错的.为什么呢? 每一句 ...
- 省队集训Day1 睡觉困难综合征
传送门:https://www.luogu.org/problem/show?pid=3613 [题解] 按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做. 写棵LCT,维护正反两种权值, ...
- 【BZOJ】1700: [Usaco2007 Jan]Problem Solving 解题
[题意]给定n道题,每月末发放工资m,要求从1解到n,每道题需要在当月初付费ai,下月初付费bi,多道题可以安排在同月,求最少月数. [算法]DP [题解]参考自:[bzoj1700]Problem ...
- Linux 中使用 dd 测试磁盘性能
翻译自 : Linux I/O Performance Tests using dd 基本说明 dd 可以用来做简单的低级别复制文件. 这样做, 一般都是可一直直接访问设备文件. 需要说明的是, 错误 ...
- this的九种常用场景(转子jb51.net)
[场景1]全局环境中的this指向全局对象 ; alert(a); b = ; alert( ; [场景2]对象内部函数的this指向调用函数的当前对象 ; var bar = { a: , test ...
- Yii 1.1.17 五、分页类、关联模型、权限验证与默认页面跳转
一.分页类使用 1.在控制器中 // 实例化 $criteria = new CDbCriteria(); $articleModel = Article::model(); // 分页 $total ...
- python基础===python实现截图
python实现全屏截图: from PIL import ImageGrab im = ImageGrab.grab() im.save('F:\\12.png')
- 离线安装SDK
1.下载android-sdk_rXX-windows.zip(XX为版本号,也可以下.exe版的不过没试过) 2.下载SDK 2.1.在浏览器输入http://dl-ssl.google.com/a ...
- jquery获取元素索引值index()的例子
如果参数是一组DOM元素或者jQuery对象,那么返回值就是传递的元素相对于原先集合的位置. 如果参数是一个选择器,那么返回值就是原先元素相对于选择器匹配元素中的位置.如果找不到匹配的元素,则返回-1 ...
- lnmp的安装--mysql
1.前期准备 创建组:groupadd mysql 创建用户:useradd -r -g mysql mysql 创建mysql文件夹于数据存放文件夹data mkdir -p /usr/www/my ...