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 理解的更多相关文章

  1. React-安装和配置redux调试工具Redux DevTools

    chrome扩展程序里搜索Redux DevTools进行安装 新建store的时候,进行如下配置. import { createStore, applyMiddleware ,compose} f ...

  2. 25.redux回顾,redux中的action函数异步

    回顾:Redux: 类似于 Vuex 概念:store/reducer/action action:动作 {type,.....} 一定要有type 其他属性不做限制 reducer:通过计算产生st ...

  3. 手把手教你撸一套Redux(Redux源码解读)

    Redux 版本:3.7.2 Redux 是 JavaScript 状态容器,提供可预测化的状态管理. 说白了Redux就是一个数据存储工具,所以数据基础模型有get方法,set方法以及数据改变后通知 ...

  4. 记一次修改框架源码的经历,修改redux使得redux 可以一次处理多个action,并且只发出一次订阅消息

    redux是一个数据状态管理的js框架,redux把行为抽象成一个对象,把状态抽象成一个很大的数据结构,每次用户或者其他什么方式需要改变页面都可以理解成对数据状态的改变,根据出发这次改变的不同从而有各 ...

  5. [Redux] Understand Redux Higher Order Reducers

    Higher Order Reducers are simple reducer factories, that take a reducer as an argument and return a ...

  6. [Redux] Filtering Redux State with React Router Params

    We will learn how adding React Router shifts the balance of responsibilities, and how the components ...

  7. 理解Redux以及如何在项目中的使用

    今天我们来聊聊Redux,这篇文章是一个进阶的文章,建议大家先对redux的基础有一定的了解,在这里给大家推荐一下阮一峰老师的文章: http://www.ruanyifeng.com/blog/20 ...

  8. Redux 中间件的执行顺序理解

    Redux.applyMiddleware(thunk, middleware1) 和 Redux.applyMiddleware(middleware1, thunk) 的区别: <!DOCT ...

  9. 【React】360- 完全理解 redux(从零实现一个 redux)

    点击上方"前端自习课"关注,学习起来~ 前言 记得开始接触 react 技术栈的时候,最难理解的地方就是 redux.全是新名词:reducer.store.dispatch.mi ...

随机推荐

  1. 【Codeforces】868C. Qualification Rounds

    [题目]C. Qualification Rounds [题意]给定n个问题和K个人,给定每个人知道的问题列表,求能否找到一个非空问题集合,满足每个人知道的集合中问题数量都不超过集合总题数的一半.n& ...

  2. 【51NOD】消灭兔子

    [算法]贪心 #include<cstdio> #include<algorithm> #include<cstring> #include<queue> ...

  3. 原始套接字&&数据链路层访问

    1. 原始套接字能力: (1) 进程可以读写ICMP,IGMP等分组,如ping程序: (2) 进程可以读写内核不处理协议字段的ipv4数据报:如OSPF等: (3) 进程可以使用IP_HDRINCL ...

  4. sublime Text3 === 无法输入input的问题解决办法

    sublimetext无法对input或者raw_input执行.因此搜了很多方法后,解决了这个问题: 1.先下载插件sublimerepl ,如果无法下载,请点击https://github.com ...

  5. 【bzoj4562】HAOI2016食物链

    记忆化搜索水过去了…… QwQ #include<bits/stdc++.h> #define N 400010 typedef long long ll; using namespace ...

  6. Python数据处理实战

    一.运行环境 1.python版本 2.7.13 博客代码均是这个版本2.系统环境:win7 64位系统 二.需求 对杂乱文本数据进行处理 部分数据截图如下,第一个字段是原字段,后面3个是清洗出的字段 ...

  7. 亚马逊EC2根硬盘空间扩容

    买的系统盘为32G,结果发现只使用了8G,剩下的都未分配 lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda : 32G disk └─xvda1 : ...

  8. mybatis开启字段自动映射为java驼峰命名规则

    <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> & ...

  9. FineReport——JS二次开发(工具栏按钮事件及说明)

    首先获取到这个模板对象: document.getElementById('reportFrame').contentWindow.contentPane.方法名称(); 方法以及说明:

  10. 关于那些Android中不常用的设置属性

    很多在manifest中的属性我们经常遗忘了它们,或者经常看到但又不是很明白它的作用.那么在这里我就拿了一些属性简单的解释一下,防止以后碰到却不知道其中的意思.不是很全,以后会断断续续的补充吧 一.a ...