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. windows下用时间戳创建文件名

    英文环境下: echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.zip 中文: ...

  2. 炒鸡简单的canvas粒子(山东数漫江湖)

    位图的canvas一直不会被svg比下去的原因了. 俗话说,须弥芥子,是大小之说,也有以小见大之说,颗颗粒子,足以构建宏大效果. 这是一篇炒鸡简单的canvas粒子教程,主要是讲如何粒子特效的原理,一 ...

  3. deepin 快捷键

    从此脱离鼠标

  4. 【Python学习笔记】有关包的基本知识

    python的包(package)是一个有层次的文件目录结构.它定义了一个由模块和子包组成的Python应用程序执行环境. AAA/ __init__.py bbb.py CCC/ __init__. ...

  5. 使用 ftrace 调试 Linux 内核,第 1 部分【转】

    转自:http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace1/index.html ftrace 是 Linux 内核中提供的一种调试工具.使用 ...

  6. 64_l1

    L-function-1.23-18.fc26.i686.rpm 13-Feb-2017 23:19 154562 L-function-1.23-18.fc26.x86_64.rpm 13-Feb- ...

  7. 【数位dp入门】【HDU4734】F(x)

    记录减的状态,表示还要凑多少才能达到当前值. 然后进行枚举即可.注意状态数不能重复. #include<bits/stdc++.h> #define N 10010 using names ...

  8. centos7.4关闭防火前

    systemctl stop firewalld.service #停止firewallsystemctl disable firewalld.service #禁止firewall开机启动firew ...

  9. leetcode 之Single Number(13)

    看见这题我的第一反应是用哈希来做,不过更简洁的做法是用异或来处理,只要是偶数个都为0(0和任意数异或仍为数本身). int singleNumber(int A[], int n) { ; ; i & ...

  10. Java中的原子操作类

    转载: <ava并发编程的艺术>第7章 当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可 ...