redux-thunk是作为redux的一个中间件。我们可以使用中间件来进行日志记录、创建崩溃报告、调用异步接口等工作,简单来说中间件都是对store.dispatch()的增强。
Redux的核心概念其实很简单:将需要修改的state都存入到store里,发起一个action用来描述发生了什么,用reducers描述action如何改变state tree 。创建store的时候需要传入reducer,真正能改变store中数据的是store.dispatch API。
1.redux-thunk

如图。view在redux中会派发一个action,action通过store的dispatch方法派发给store,store接收到action,连同之前到state,一起传给reducer,reducer返回一个新到数据给store,store去改变自己到state。这是redux的一个标准流程,那么我们说redux的中间件指的是谁和谁的之间,大家一定要记住, redux的中间件指的是action和store之间。之前我们说action只能是一个对象,所以action是一个对象直接派发给了store。 但是现在,当我们使用了redux-thunk之后,action可以是函数了。
redux中间件其实原理是非常简单的,它就是对store对dispatch方法做一个升级,之前这个dispatch方法只能接收一个对象,现在升级之后,就可以接收对象,也可以接收函数了。 当然这里用什么对他进行一个升级呢?用redux-thunk对他进行了升级。当然中间件不只redux-thunk这一个,实际上redux中间件非常多,比如说我们说的redux-log,可以记录action每次派发的日志,那他怎么记录呢?其实也很简单,每次调用 action的时候,都会通过dispatch把这个action传递给store,那么我可以对dispatch做一个升级,dispatch不仅仅把action传递给store,而且在每次传递之前呢,还通过console.log,把这个action打印出来。这样就写了一个redux-log的中间件。他可以在每次派发action的时候,把这个action打印在控制台里面。
redux中间件,除了redux-thunk,redux-log这样的东西,还有一个中间件,叫做redux-saga。他的应用范围也非常广,redux-saga也是解决redux中间异步问题的中间件。不同于redux-thunk。redux-thunk是把异步操作放在action里面操作。而redux-saga采用的设计思想是,单独的把一个异步逻辑拆分出来,放在一个异步文件里面管理,基本上掌握了redux-thunk和redux-saga这两者的设计思路之后呢,再去做redux里面的异步逻辑,或者说复杂的逻辑,如何去拆分,就比较明白了。
实例:
项目结构图

package.json
"devDependencies": {
"@babel/core": "^7.18.5",
"@babel/plugin-transform-runtime": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@babel/preset-react": "^7.17.12",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.0.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.1",
"sass": "^1.52.3",
"sass-loader": "^13.0.0",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.3",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.2",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"@babel/runtime": "^7.18.3",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"react-router-dom": "^5.2.1",
"redux": "^4.2.0",
"redux-thunk": "^2.4.0",
"axios": "^0.27.2"
}
store/reducer.js
let defaultState = {
i: 0,
msg: 'hello,world'
}
let reducer = (state = defaultState, action) => {
if (action.type === 'axios_getdata') {
let tempState = JSON.parse(JSON.stringify(state))
tempState.i = action.i
tempState.msg = action.msg
return tempState
}
return state
}
export default reducer
store/index.js
import {legacy_createStore as createStore,applyMiddleware} from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk'
let store = createStore(reducer,applyMiddleware(thunk))
export default store
App.js
import React, {Component} from 'react'
import store from './store'
import axios from 'axios'
export default class App extends Component {
constructor() {
super()
this.state = store.getState()
store.subscribe(() => {
this.setState(store.getState())
})
}
render() {
return (
<div>
i={this.state.i},msg={this.state.msg}
<br/>
<button onClick={this.change.bind(this)}>更改内容</button>
</div>
)
}
change() {
//当我们使用了redux-thunk之后,action可以是函数了
store.dispatch(this.changeContentFunction)
}
changeContentFunction = (dispatch) => {
axios.get("/data.json")
.then(resp => {
const action = {
type: 'axios_getdata',
i: resp.data.i,
msg: resp.data.msg
}
dispatch(action)
})
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(<App />,document.getElementById('root'));
public/data.json
{
"i": 100,
"msg": "hello,react"
}
运行结果:
