Redux Toolkit の非同期操作
createAsyncThunk
以前の開発では、redux-thunk ミドルウェアを使用して、ディスパッチで非同期操作を有効にしました. 実際、Redux Toolkit ツールキットには、デフォルトで Thunk 関連の機能が統合されています.関数を介して非同期アクションを作成できます
createAsyncThunk 関数には次のパラメーターがあります。
パラメータ 1: 着信イベント タイプ type
パラメーター 2: 非同期操作を実行できる関数を渡すか、非同期関数を直接渡すこともできます
export const fetchHomeMultidataAction = createAsyncThunk("fetch/homemultidata", async () => {
const res = await axios.get("http://123.207.32.32:8000/home/multidata")
const banners = res.data.data.banners.list
const recommends = res.data.data.recommends.list
})f
createAsyncThunk によって作成されたアクションがディスパッチされると、次の 3 つの状態になります。
保留中: アクションは発行されますが、最終結果はありません。
満たされた: 最終結果を取得します (戻り値のある結果);
拒否: 実行中にエラーが発生したか、例外がスローされました。
createSlice の entraReducer でこれらの結果をリッスンできます。
注: 作成したアクション: fetchHomeMultidataAction によって返された結果は、以下のリスナー関数のアクション パラメーターに渡されます。
取得する
actions.payload
(アクションを構造化し、ペイロードを直接取得することもできます)
// extraReducers中针对异步action, 监听它的状态
extraReducers: {
// 处于padding状态时回调
[fetchHomeMultidataAction.pending](state, actions) {
console.log("正处于pending状态")
},
// 处于fulfilled状态时回调
[fetchHomeMultidataAction.fulfilled](state, actions) {
console.log("正处于fulfilled状态")
},
// 处于rejected状态时回调
[fetchHomeMultidataAction.rejected](state, actions) {
console.log("正处于rejected状态")
}
}
ネットワーク リクエストの流れを示します。
方式一
:home.js で、createAsyncThunk 関数を使用して非同期アクションを作成します。
次に、extraReducers でこの非同期アクションの状態を監視し、満たされた状態になったら、ネットワークから要求されたデータを取得し、元の状態でデータを変更します。
import {
createSlice, createAsyncThunk } from "@reduxjs/toolkit"
import axios from "axios"
// 创建一个异步的action
export const fetchHomeMultidataAction = createAsyncThunk("fetch/homemultidata", async () => {
const res = await axios.get("http://123.207.32.32:8000/home/multidata")
// 返回结果会传递到监听函数的actions中
return res.data
})
const homeSlice = createSlice({
name: "home",
initialState: {
banners: [],
recommends: []
},
// extraReducers中针对异步action, 监听它的状态
extraReducers: {
[fetchHomeMultidataAction.fulfilled](state, {
payload }) {
// 在fulfilled状态下, 将state中的banners和recommends修改为网络请求后的数据
state.banners = payload.data.banner.list
state.recommends = payload.data.recommend.list
}
}
})
export default homeSlice.reducer
方式二
:extraReducers の listen 状態で状態を変更したくない場合は、別の方法があります。
作成した非同期アクション fetchHomeMultidataAction は、2 つのパラメーターを受け入れます。
- パラメータ 1、extraInfo: この非同期アクションをディスパッチするときに、パラメータが渡された場合、extraInfo に配置されます。
- パラメータ 2、ストア: 2 番目のパラメータはストアを渡します。
このようにして、結果を取得した後、ディスパッチを通じてストアの状態を変更できます。非同期アクションの状態を監視する必要はありません。
import {
createSlice, createAsyncThunk } from "@reduxjs/toolkit"
import axios from "axios"
// 创建一个异步的action
export const fetchHomeMultidataAction = createAsyncThunk(
"fetch/homemultidata",
// 有传递过来两个个参数, 从store里面解构拿到dispatch
async (extraInfo, {
dispatch }) => {
// 1.发送网络请求获取数据
const res = await axios.get("http://123.207.32.32:8000/home/multidata")
// 2.从网络请求结果中取出数据
const banners = res.data.data.banner.list
const recommends = res.data.data.recommend.list
// 3.执行dispatch, 派发action
dispatch(changeBanners(banners))
dispatch(changeRecommends(recommends))
}
)
const homeSlice = createSlice({
name: "home",
initialState: {
banners: [],
recommends: []
},
reducers: {
changeBanners(state, {
payload }) {
state.banners = payload
},
changeRecommends(state, {
payload }) {
state.recommends = payload
}
}
})
export const {
changeBanners, changeRecommends } = homeSlice.actions
export default homeSlice.reducer
いずれにしても、ページの componentDidMount ライフサイクルで非同期アクションをディスパッチして、ネットワーク リクエストを送信する必要があります。
import React, {
PureComponent } from 'react'
import {
connect } from 'react-redux'
import {
fetchHomeMultidataAction } from '../store/features/home'
export class About extends PureComponent {
// 生命周期中, 调用映射的方法派发异步的action
componentDidMount() {
this.props.fetchHomeMultidata()
}
render() {
const {
banners, recommends } = this.props
return (
<div>
<h2>About</h2>
<h2>轮播图数据</h2>
<ul>
{
banners.map(item => {
return <li key={
item.acm}>{
item.title}</li>
})
}
</ul>
<h2>推荐数据</h2>
<ul>
{
recommends.map(item => {
return <li key={
item.acm}>{
item.title}</li>
})
}
</ul>
</div>
)
}
}
const mapStateToProps = (state) => ({
banners: state.home.banners,
recommends: state.home.recommends
})
// 派发异步的action
const mapDispatchToProps = (dispatch) => ({
fetchHomeMultidata() {
dispatch(fetchHomeMultidataAction())
}
})
export default connect(mapStateToProps, mapDispatchToProps)(About)