← 返回首页
React基础教程(十九)
发表时间:2022-07-04 20:40:53
redux-thunk

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"
}

运行结果: