Redux异步操作redux-thunk

文章目录

        • 源码
        • 这个功能添加到什么地方呢?
        • 使用方法
        • 例子
        • 启动redux-devtools 工具

Action 发出以后,Reducer 立即算出 State,这叫做同步;Action 发出以后,过一段时间再执行 Reducer,这就是异步.
怎么才能 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件;(xxxMiddleware)
redux-thunk 是一个比较流行的 redux 异步 action 中间件;


源码

源码


这个功能添加到什么地方呢?

(1)Reducer:纯函数,只承担计算 State 的功能,不合适承担其他功能,也承担不了,因为理论上,纯函数不能进行读写操作。
(2)View:与 State 一一对应,可以看作 State 的视觉层,也不合适承担其他功能。
(3)Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。

以上都不能添加,所以只有 发送 action 的这个步骤可以,也就是 dispatch(action)方法 。可以添加功能;(也就是在发送对应的action中实现异步action)


中间件就是一个函数,对 dispatch() 方法 进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。


使用方法

  1. 安装 npm i redux-thunk -S
  2. 导入中间键:applyMiddleware
import {applyMiddleware} from 'redux';
  1. 导入并接收一下redux-thunk;
//接收的名字有意义就行
import thunk from 'redux-thunk'
  1. 在创建store的时候激活redux-thunk
createStore(reducer,applyMiddleware(thunk))
  1. 在 action 中,创建函数,利用redux-thunk 帮助统一异步和同步 action 的调用方式;(把异步过程放入到要发送的 action中)

例子

还是利用上一篇的 Redux的基本使用 的这个例子;


在store文件夹的 index.js文件 中,因为要在创建store仓储实例的使用引入中间键
这里的compose到下边再说

import { createStore, applyMiddleware, compose } from 'redux';
// 这个reducer是聚合了所有的reducer的一个reducer
import reducer from '../reducers/index.js';


// 实现异步操作,利用这个中间键
import thunk from 'redux-thunk'


export default function Store(initState) {
    // 创建store的时候,还有第三个参数,用来启动第三方redux的插件工具
    //applyMiddleware(thunk) 用来激活redux-thunk
    return createStore(reducer, initState, compose(applyMiddleware(thunk),window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()))
}

添加异步功能是要在dispatch(action) 的action中实现异步action的
此例子是在actions文件夹下的 user.js文件 中,实现异步action

import * as userConstants from '../constants/user.js'

const loginRequest = () => {
    // 模拟登陆请求,发送一个登陆请求,返回一个promise对象,resolute的时候把参数传进去,也就是登陆成功以后的结果
    return new Promise((resolve) => {
        window.setTimeout(() => {
            // 这个dispatch就是我们登陆完以后,要干什么,跟按钮点击事件中的dispatch是一样的
            // 2秒之后,然后再发送一个dispatch(update),这里的update是一个同步的action
            resolve({
                isLogin: true,
                nickname: "用户昵称",
                avatar: "http://biadu.com"
            })
        }, 2000)
    })
}

// 这里的action 接受一个数据参数,叫data,名字无所谓
export const login = (data) => {
    // 异步的action
    return async (dispatch) => {
        // 这个是通知视图中,我们的异步正在操作,让它loading加载中,不能再点击按钮
        dispatch(update({
            loading: true
        }))

        // 这个是拿到数据以后,再去dispatch(update)
        const res = await loginRequest()
        dispatch(update({
            ...res,
            // 拿到数据以后,再把loading状态取消
            loading: false
        }))
    }
}

注: 这个文件后边的代码,在 Redux的基本使用 中;


此例子是 用户登录状态 ,所以当用户点击按钮的时候,提示用户,正在登录…,2秒后便执行 dispatch(update) 函数更新数据,
在 创建 store仓储实例的时候,传初始化默认数据的时候给一个 isloading:false 状态,
在src目录下的 index.js 文件中

const store = Store({
    user: {
        isLogin: false,
        loading: false
    },
    city: {
        "029": "北京"
    }
})

在是视图层显示loading状态;
在App.js中添加

class App extends Component {
  render() {
    console.log(this.props)
    const { user } = this.props
    return (
      <div className="App">
        用户状态↓
        <div>
          {user.isLogin ? '欢迎你' : '未登录'}
        </div>
        <div>
          {user.loading ? "正在加载中...." : ""}
        </div>

        {/* 通过触发 login这个action,进行数据的更新,并且再多传一下两个参数,点击按钮,用户状态将变成,已登录,因为login所对应的reducer数据处理,isLogin:true */}
        <button onClick={() => {
          this.props.dispatch(userActions.login({ account: "test", password: "123" }))
        }}>登录</button>
      </div>
    );
  }
}

启动redux-devtools 工具

因为 redux-thunk 和 redux-devtools 都是第三方的插件,createStore() 传参,不能单独传,所以只能借助于 compose()函数; 如果还有第三方的东西,依次往后添加就行了!!!

createStore(reducer, initState, compose(applyMiddleware(thunk),window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()))

你可能感兴趣的:(前端,React,Redux)