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. [BZOJ1076][SCOI2008]奖励关解题报告|状压DP

    你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再吃). 宝 ...

  2. lua滚动文字效果

    基本的思想都是创建一个clippingNode,将要截取的节点添加到clippingNode中,节点加上action即可. 下面是左右滚动的代码,如果是上下滚动,更简单了,只需修改Y坐标即可,都不用动 ...

  3. 教你 Shiro 整合 SpringBoot,避开各种坑(山东数漫江湖)

    依赖包 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-sprin ...

  4. jq_常用开发模块

    1.循环模块 var html = ""; $.each(data, function(k, v) { html += '<li>' + '<div>' + ...

  5. 3.0docker操作

    登录镜像资源 docker login daocloud.io username: password: docker login : 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方 ...

  6. MySQL:Can't create test file XXX.lowe-test

    问题说明 今天部署MySQL,在使用mysql_install_db,初始化数据库时报如下错误 180622 11:36:38 mysqld_safe Starting mysqld daemon w ...

  7. Python3 Socket和SocketServer 网络编程

    socket只能实现同时一个服务和一个客户端实现交互,socketserver可以实现多个客户端同时和服务端交互 1.利用Socket编写简单的同一个端口容许多次会话的小案例: 服务端: #!/usr ...

  8. ZZ:Solaris 10 软件包分析

    ZZ:Solaris 10 软件包分析 http://blog.chinaunix.net/uid-22759617-id-276756.html # Last updated: 2006-02-14 ...

  9. 刷新SqlServer数据库中所有的视图

    ALTER PROCEDURE sp_refallview AS --刷新所有视图 DECLARE @ViewName VARCHAR(MAX); DECLARE @i INT; ; DECLARE ...

  10. sicily 1001. Fibonacci 2

    1001. Fibonacci 2   Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn-1 + F ...