Redux的三大原則
? 單一數(shù)據(jù)源
? ? 整個(gè)應(yīng)用程序的state被存儲(chǔ)在一顆object tree中,并且這個(gè)object tree只存儲(chǔ)在一個(gè) store 中:
? ? Redux并沒有強(qiáng)制讓我們不能創(chuàng)建多個(gè)Store,但是那樣做并不利于數(shù)據(jù)的維護(hù);
? ? 單一的數(shù)據(jù)源可以讓整個(gè)應(yīng)用程序的state變得方便維護(hù)、追蹤、修改;
? State是只讀的
? ? 唯一修改State的方法一定是觸發(fā)action,不要試圖在其他地方通過任何的方式來修改State:
? ? 這樣就確保了View或網(wǎng)絡(luò)請(qǐng)求都不能直接修改state,它們只能通過action來描述自己想要如何修改state;
? ? 這樣可以保證所有的修改都被集中化處理,并且按照嚴(yán)格的順序來執(zhí)行,所以不需要擔(dān)心race condition(竟態(tài))的問題;
? 使用純函數(shù)來執(zhí)行修改
? ? 通過reducer將 舊state和 actions聯(lián)系在一起,并且返回一個(gè)新的State:
? ? 隨著應(yīng)用程序的復(fù)雜度增加,我們可以將reducer拆分成多個(gè)小的reducers,分別操作不同state tree的一部分;
? ? 但是所有的reducer都應(yīng)該是純函數(shù),不能產(chǎn)生任何的副作用;
Redux官方圖
react-redux使用
? 安裝react-redux:
yarn add react-redux
? 1、創(chuàng)建store管理全局狀態(tài)
-src
—store
------- constants.js
先創(chuàng)建要使用的type常量
export const ADD_NUMBER = "add_number"
export const SUB_NUMBER = "sub_number"
export const CHANGE_BANNERS = "change_banners"
export const CHANGE_RECOMMENDS = "change_recommends"
-src
—store
------- reducer.js
再創(chuàng)建reducer管理狀態(tài)
import * as actionTypes from "./constants"
const initialState = {
counter: 100,
banners: [],
recommends: []
}
function reducer(state = initialState, action) {
switch (action.type) {
case actionTypes.ADD_NUMBER:
return { ...state, counter: state.counter + action.num }
case actionTypes.SUB_NUMBER:
return { ...state, counter: state.counter - action.num }
case actionTypes.CHANGE_BANNERS:
return { ...state, banners: action.banners }
case actionTypes.CHANGE_RECOMMENDS:
return { ...state, recommends: action.recommends }
default:
return state
}
}
export default reducer
-src
—store
------- index.js
在index導(dǎo)出整個(gè)store
import { createStore } from "redux"
import reducer from "./reducer"
const store = createStore(reducer)
export default store
-src
—store
------- actionCreators.js
創(chuàng)建actionCreators,放修改狀態(tài)的函數(shù)
import * as actionTypes from "./constants"
import axios from "axios"
export const addNumberAction = (num) => ({
type: actionTypes.ADD_NUMBER,
num
})
export const subNumberAction = (num) => ({
type: actionTypes.SUB_NUMBER,
num
})
export const changeBannersAction = (banners) => ({
type: actionTypes.CHANGE_BANNERS,
banners
})
export const changeRecommendsAction = (recommends) => ({
type: actionTypes.CHANGE_RECOMMENDS,
recommends
})
export const fetchHomeMultidataAction = () => {
// 如果是一個(gè)普通的action, 那么我們這里需要返回action對(duì)象
// 問題: 對(duì)象中是不能直接拿到從服務(wù)器請(qǐng)求的異步數(shù)據(jù)的
// return {}
return function(dispatch, getState) {
// 異步操作: 網(wǎng)絡(luò)請(qǐng)求
// console.log("foo function execution-----", getState().counter)
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
// dispatch({ type: actionTypes.CHANGE_BANNERS, banners })
// dispatch({ type: actionTypes.CHANGE_RECOMMENDS, recommends })
dispatch(changeBannersAction(banners))
dispatch(changeRecommendsAction(recommends))
})
}
// 如果返回的是一個(gè)函數(shù), 那么redux是不支持的
// return foo
}
?? 2、在項(xiàng)目index.js根節(jié)點(diǎn)引用
-src
— index.js
? 3、 在需要使用redux的頁(yè)面或者組件中,通過connect高階組件映射到該組件的props中
? 解耦store和class組件的耦合
redux中異步操作
? redux也引入了中間件(Middleware)的概念:
? ? 這個(gè)中間件的目的是在dispatch的action和最終達(dá)到的reducer之間,擴(kuò)展一些自己的代碼;
? ? 比如日志記錄、調(diào)用異步接口、添加代碼調(diào)試功能等等;
? 我們現(xiàn)在要做的事情就是發(fā)送異步的網(wǎng)絡(luò)請(qǐng)求,所以我們可以添加對(duì)應(yīng)的中間件:
? ? 這里官網(wǎng)推薦的、包括演示的網(wǎng)絡(luò)請(qǐng)求的中間件是使用 redux-thunk
? redux-thunk是如何做到讓我們可以發(fā)送異步的請(qǐng)求呢?
? ? 我們知道,默認(rèn)情況下的dispatch(action),action需要是一個(gè)JavaScript的對(duì)象;
? ? redux-thunk可以讓dispatch(action函數(shù)),action可以是一個(gè)函數(shù);
? ? 該函數(shù)會(huì)被調(diào)用,并且會(huì)傳給這個(gè)函數(shù)一個(gè)dispatch函數(shù)和getState函數(shù);
? ? dispatch函數(shù)用于我們之后再次派發(fā)action;
? ? getState函數(shù)考慮到我們之后的一些操作需要依賴原來的狀態(tài),用于讓我們可以獲取之前的一些狀態(tài);
如何使用redux-thunk
? 1.安裝redux-thunk
如何使用redux-thunk
yarn add redux-thunk
? 2.在創(chuàng)建store時(shí)傳入應(yīng)用了middleware的enhance函數(shù)
? ? 通過applyMiddleware來結(jié)合多個(gè)Middleware, 返回一個(gè)enhancer;
? ? 將enhancer作為第二個(gè)參數(shù)傳入到createStore中;
// 通過applyMiddleware來結(jié)合多個(gè)Middleware, 返回一個(gè)enhancer
const enhancer = applyMiddleware(thunkMiddleware);
// 將enhancer作為第二個(gè)參數(shù)傳入到createStore中
const store = createStore(reducer, enhancer);
? 3.定義返回一個(gè)函數(shù)的action:
? ? 注意:這里不是返回一個(gè)對(duì)象了,而是一個(gè)函數(shù);
? ? 該函數(shù)在dispatch之后會(huì)被執(zhí)行;
const getHomeMultidataAction = () => {
return (dispatch) => {
axios.get("http://123.207.32.32:8000/home/multidata").then(res => {
const data = res.data.data;
dispatch(changeBannersAction(data.banner.list));
dispatch(changeRecommendsAction(data.recommend.list));
})
}
}
combineReducers函數(shù)
? 事實(shí)上,redux給我們提供了一個(gè)combineReducers函數(shù)可以方便的讓我們對(duì)多個(gè)reducer進(jìn)行合并:
? 那么combineReducers是如何實(shí)現(xiàn)的呢?
? ? 事實(shí)上,它也是將我們傳入的reducers合并到一個(gè)對(duì)象中,最終返回一個(gè)combination的函數(shù)(相當(dāng)于我們之前的reducer函
數(shù)了);
? ? 在執(zhí)行combination函數(shù)的過程中,它會(huì)通過判斷前后返回的數(shù)據(jù)是否相同來決定返回之前的state還是新的state;文章來源:http://www.zghlxwxcb.cn/news/detail-802325.html
? ? 新的state會(huì)觸發(fā)訂閱者發(fā)生對(duì)應(yīng)的刷新,而舊的state可以有效的組織訂閱者發(fā)生刷新;文章來源地址http://www.zghlxwxcb.cn/news/detail-802325.html
到了這里,關(guān)于【React】Redux的使用詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!