首先需要搞懂什么是同步action和异步action
如果返回的action,返回的值是一个对象就是同步action
如果返回的action,返回的值是一个函数就是异步action
异步action的使用示例
使用异步action,需要安装一个中间件来支持,不然不支持返回的是函数这种形式的action(action本身是一个对象类型的)
yarn add redux-thunk
就拿这个异步加的例子来说
src—> Components—> Count ----> index.jsx
import React, {
Component } from 'react'
// 引入store,用于获取redux中保存的状态
import store from '../../redux/store'
// 引入actionCreate,专门用于action对象
import {
createDecreamentAction, createIncreamentAction,createIncrementAsyncAction} from '../../redux/count_action'
export default class Count extends Component {
// 加法
increment=()=>{
const {
value}=this.selectNumber
// 通知redux加value
store.dispatch(createIncreamentAction(value*1))
}
// 减法
decrement=()=>{
const {
value}=this.selectNumber
store.dispatch(createDecreamentAction(value*1))
}
// 奇数再加
incrementIfOdd=()=>{
const {
value}=this.selectNumber
const count=store.getState()
if (count%2!==0) {
store.dispatch(createIncrementIfOddAction(value*1))
}
}
// 异步加
incrementAsync=()=>{
const {
value}=this.selectNumber
const count=store.getState()
//使用异步的action
store.dispatch(createIncrementAsyncAction(value*1,2000))
}
render() {
return (
<div>
<h1>当前求和为:{
store.getState()}</h1>
<select ref={
c=>this.selectNumber=c} >
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={
this.increment}>+</button>
<button onClick={
this.decrement}>-</button>
<button onClick={
this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={
this.incrementAsync}>异步加</button>
</div>
)
}
}
src—>redux—>constant.js
/*
该模块是用于定义action对象中type类型的常量值,目的只有一个,便于管理的同时,防止出现拼写错误的情况
*/
export const INCREMENT='increment'
export const DECREMENT='decrement'
src—>redux—>count_reducer.js
/*
该文件是用于创建一个为Count服务的reducer,reducer的本质就是一个函数
reducer函数会接到两个参数,分别会:之前的状态(preState) ,动作对象(action)
*/
import {
INCREMENT,DECREMENT} from './constant'
const initState=0 //初始化状态
export default function countReducer(preState=initState,action){
// 从action对象中获取:type,data
const {
type,data}=action
// 根据type决定如何加工数据
switch (type) {
case INCREMENT://如果是加
return preState+data
case DECREMENT://如果是减
return preState-data
case 'incrementIfOdd':
return preState+data
case 'incrementAsync':
return preState+data
default:
return preState
}
}
src—>redux—>count_action.js
/*
该文件专门为Count组件生成action对象
*/
import {
INCREMENT,DECREMENT} from './constant'
// 返回同步action,返回的是一个对象
export const createIncreamentAction = data => ({
type:INCREMENT,data })
export const createDecreamentAction = data => ({
type:DECREMENT,data })
export const createIncrementIfOddAction = data => ({
type:'incrementIfOdd',data})
// 所谓的异步action就是指action的值为函数,异步action一般都会调用同步action,异步action不是必须要用的
export const createIncrementAsyncAction = (data,time)=>{
//这里的dispatch第一次调用action的时候已经有了,所以不需要再从store中读取了
return (dispatch)=>{
setTimeout(()=>{
//调用同步action去更新数据
dispatch(createIncreamentAction(data))
},time)
}
}
src---->redux—>store.js
使用异步action,需要安装一个中间件来支持,不然不支持返回的是函数这种形式的action(action本身是一个对象类型的)
从redux中引入applyMiddleware,引入redux-thunk,创建redux的时候使用createStore(countReducer,applyMiddleware(thunk))去应用这个中间件
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
// 引入createStore,专门用于创建redux最为核心的store对象
import {
legacy_createStore as createStore,applyMiddleware} from 'redux'
// 引入为count服务的reducer
import countReducer from './count_reducer'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
// 暴露store
export default createStore(countReducer,applyMiddleware(thunk))
src---->index.js
import React from "react";
import {
createRoot } from 'react-dom/client'; //react18的引入方式
import App from './App'
import store from './redux/store'
const root=createRoot(document.getElementById('root'))
root.render( < App />) //react18的渲染方式
// 监测redux中状态的变化,只要变化,就调用render
store.subscribe(()=>{
root.render( < App />)
})
总结
- 明确:延迟的动作不想交给组件自身,想交给action
- 何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回(非必须)
- 具体编码:
1) yarn add redux-thunk并配置在store中
2)创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务
3)异步任务有结果后,分发一个同步的action去真正操作数据 - 备注:异步action不是必须要写的,完全可以等待异步任务的结果再去分发同步action