Redux中進行異步操作(網(wǎng)絡(luò)請求)的示例方案
Redux中的異步操作
在之前簡單的案例中,redux中保存的counter是一個本地定義的數(shù)據(jù)
我們可以直接通過同步的操作來dispatch action,state就會被立即更新。
但是真實開發(fā)中,redux中保存的很多數(shù)據(jù)可能來自服務(wù)器,我們需要進行異步的請求,再將數(shù)據(jù)保存到redux中。
在之前學(xué)習(xí)網(wǎng)絡(luò)請求的時候我們講過,發(fā)生網(wǎng)絡(luò)請求我們有兩種方案, 可以直接在組件的鉤子函數(shù)中發(fā)送網(wǎng)絡(luò)請求, 再將數(shù)據(jù)存放到store中; 也可以直接在store中發(fā)生網(wǎng)絡(luò)請求
組件中進行異步操作
網(wǎng)絡(luò)請求可以在class組件的生命周期函數(shù)componentDidMount中發(fā)送,所以我們可以有這樣的結(jié)構(gòu):
我現(xiàn)在完成如下案例操作:
創(chuàng)建一個組件Category, 在該組件中發(fā)送網(wǎng)絡(luò)請求, 獲取banners和recommends的數(shù)據(jù);
在About組件中展示banners和recommends的數(shù)據(jù);
首先需要創(chuàng)建要派發(fā)的action, 以及對應(yīng)的reducer
// store/actionCreators.jsx import { CHANGE_BANNERS, CHANGE_RECOMMENDS } from "./constants" export const changeBannersAction = (banners) => ({ type: CHANGE_BANNERS, banners }) export const changeRecommendsAction = (recommends) => ({ type: CHANGE_RECOMMENDS, recommends })
// store/reducer.jsx import { CHANGE_BANNERS, CHANGE_RECOMMENDS } from "./constants" const initialState = { banners: [], recommends: [] } export default function reducer(state = initialState, action) { switch(action.type) { case CHANGE_BANNERS: return {...state, [banners: action.banners} case CHANGE_RECOMMENDS: return {...state, recommends: action.recommends} default: return state } }
在Categroy組件中發(fā)送網(wǎng)絡(luò)請求, 并將store中的banners和recommends修改為網(wǎng)絡(luò)請求后的數(shù)據(jù)
import React, { PureComponent } from 'react' import axios from 'axios' import { connect } from 'react-redux' import { changeBannersAction, changeRecommendsAction } from '../store/actionCreators' export class Category extends PureComponent { componentDidMount() { // 發(fā)送網(wǎng)絡(luò)請求, 獲取到banners和recommends數(shù)據(jù) axios.get("http://123.207.32.32:8000/home/multidata").then(res => { const banners = res.data.data.banner.list const recommends = res.data.data.recommend.list console.log(banners, recommends) // 調(diào)用映射過來的方法, 修改banners和recommends this.props.changeBanners(banners) this.props.changeRecommends(recommends) }) } render() { return ( <div>Category</div> ) } } // 映射方法用于修改store中的banners和recommends const mapDispatchToProps = (dispatch) => ({ changeBanners(banners) { dispatch(changeBannersAction(banners)) }, changeRecommends(recommends) { dispatch(changeRecommendsAction(recommends)) } }) export default connect(null, mapDispatchToProps)(Category)
目前, store中存放的就是網(wǎng)絡(luò)請求獲取到的數(shù)據(jù), 接下來就在About頁面進行展示
import React, { PureComponent } from 'react' import { connect } from 'react-redux' export class About extends PureComponent { render() { // 在props中獲取到映射過來的數(shù)據(jù) const { banners, recommends } = this.props return ( <div> <h2>輪播圖展示</h2> <ul> { banners.map(item => { return <li key={item.acm}>{item.title}</li> }) } </ul> <h2>推薦數(shù)據(jù)展示</h2> <ul> { recommends.map(item => { return <li key={item.acm}>{item.title}</li> }) } </ul> </div> ) } } const mapStateToProps = (state) => ({ banners: state.banners, recommends: state.recommends }) // 表示將數(shù)據(jù)映射到About組件中 export default connect(mapStateToProps)(About)
redux中進行異步操作
上面的代碼有一個缺陷:
我們必須將網(wǎng)絡(luò)請求的異步代碼放到組件的生命周期中來完成;
事實上,網(wǎng)絡(luò)請求到的數(shù)據(jù)也屬于我們狀態(tài)管理的一部分,更好的一種方式應(yīng)該是將其也交給redux來管理;
但是在redux中如何可以進行異步的操作呢?
答案就是使用中間件(Middleware), 如果學(xué)習(xí)過Express或Koa框架的小伙伴對中間件的概念一定不陌生;
由于在正常情況下,
store.dispatch()
只能派發(fā)一個對象, 不能派發(fā)函數(shù); 如果dispatch想要派發(fā)函數(shù), 我們必須要使用中間件對該store進行增強
使用中間件, 在redux中發(fā)送網(wǎng)絡(luò)請求
首先安裝redux-thunk庫, 引入中間件
安裝redux-thunk庫:
npm i redux-thunk
, 在該庫中有一個中間件thunk, 如下方式應(yīng)用thunk中間件
import { createStore, applyMiddleware } from "redux"; import reducer from "./reducer"; // 導(dǎo)入中間件 import thunk from "redux-thunk"; // 應(yīng)用中間件 const store = createStore(reducer, applyMiddleware(thunk)) export default store
應(yīng)用之后,
store.dispatch()
就可以派發(fā)函數(shù)了
// 定義一個返回函數(shù)的action export const fetchHomeMultidataAction = () => { function foo() { console.log("aaa") } return foo }
// 派發(fā)action const mapDispatchToProps = (dispatch) => ({ fetchHomeMultidata() { // 派發(fā)一個函數(shù), 內(nèi)部返回的函數(shù)自動執(zhí)行 dispatch(fetchHomeMultidataAction()) } })
自動執(zhí)行action中的返回的函數(shù)時, 會傳給這個函數(shù)一個dispatch函數(shù)和getState函數(shù);
dispatch函數(shù)
: 用于我們之后再次派發(fā)action;
getState函數(shù)
: 考慮到我們之后的一些操作需要依賴原來的狀態(tài),調(diào)用getState函數(shù)可以讓我們可以獲取之前的一些狀態(tài);我們就可以在返回的該函數(shù)中, 編寫異步的網(wǎng)絡(luò)請求相關(guān)代碼
import axios from "axios" export const changeBannersAction = (banners) => ({ type: CHANGE_BANNERS, banners }) export const changeRecommendsAction = (recommends) => ({ type: CHANGE_RECOMMENDS, recommends }) export const fetchHomeMultidataAction = () => { // 派發(fā)時返回的該函數(shù)自動執(zhí)行, 且傳入兩個參數(shù)dispatch, getState return (dispatch, getState) => { axios.get("http://123.207.32.32:8000/home/multidata").then(res => { const banners = res.data.data.banner.list const recommends = res.data.data.recommend.list // 獲取到數(shù)據(jù)后在派發(fā)action dispatch(changeBannersAction(banners)) dispatch(changeRecommendsAction(recommends)) }) } }
到此這篇關(guān)于Redux中進行異步操作(網(wǎng)絡(luò)請求)的方案的文章就介紹到這了,更多相關(guān)Redux異步操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)99乘法表及隔行變色實例代碼
最近做了個項目是要求實現(xiàn)99乘法表隔行變色,本文給大家分享通過多種方式實現(xiàn)js 99 乘法表,感興趣的朋友一起看看吧2016-02-02javascript實現(xiàn)狀態(tài)欄中文字動態(tài)顯示的方法
這篇文章主要介紹了javascript實現(xiàn)狀態(tài)欄中文字動態(tài)顯示的方法,涉及JavaScript基于時間函數(shù)動態(tài)操作頁面元素屬性的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10JS 新增Cookie 取cookie值 刪除cookie 舉例詳解
cookie很實用的一個功能,可以判斷某個狀態(tài),下面與大家分享下JS 如何新增Cookie 取cookie值 刪除cookie,感興趣的朋友可以參考下2014-10-10