在學(xué)習(xí)react-redux之前我們需要對(duì)redux有個(gè)大概的了解,后面的文章會(huì)介紹redux的中間件和redux在react中的應(yīng)用捍岳。
redux在react中的作用琉朽?
redux的作用非常簡(jiǎn)單高诺,簡(jiǎn)單來說就是幫助我們統(tǒng)一管理react組件的state狀態(tài)。
這在剛開始看來是沒有什么作用并且增加了項(xiàng)目的復(fù)雜度魏蔗,但是當(dāng)組件有大量的變化和異步回調(diào)時(shí),我們面臨的就是一團(tuán)漿糊痹筛,代碼以后也難以維護(hù)莺治,而Redux的作用就是幫助我們解決這個(gè)問題。
安裝
你只需要在項(xiàng)目目錄下執(zhí)行npm install --save redux
但這只是本體帚稠,redux強(qiáng)大之處在于有各種的工具和中間件谣旁,比如可以安裝以下的套餐。
npm install --save redux-actions
npm install --save react-redux
npm install --save redux-thunk
npm install --save redux-promise
npm install --save-dev redux-devtools
Action
Action字面意思就是一個(gè)行為滋早,它的作用就是把更新組件狀態(tài)的每個(gè)動(dòng)作都變?yōu)橐粋€(gè)抽象的行為榄审,比如登錄,請(qǐng)求數(shù)據(jù)杆麸,頁面跳轉(zhuǎn)等等搁进。
本質(zhì)上講Action就是按照規(guī)則定義的對(duì)象,其中type是必須的角溃,定義了Action動(dòng)作的名稱拷获,其他屬性可以自己定義。
{
type: 'LOGIN_IN',
payload: 'data'
}
而創(chuàng)建這個(gè)對(duì)象的方法就叫做ActionCreator减细,比如這樣:
function loginIn(name: ?string, pass : ?string) {
return {
type:"LOGIN_IN",
data:{
username: name,
password: pass,
},
};
}
在redux-actions中提供了createAction
方法, 這個(gè)方法會(huì)返回一個(gè)符合FSA標(biāo)準(zhǔn)的ACTION匆瓜。
第一個(gè)參數(shù)是Action的type。
第二個(gè)參數(shù)表示action傳遞的數(shù)據(jù)未蝌,會(huì)被放入創(chuàng)建的action中的payload字段中驮吱。
第三個(gè)參數(shù)會(huì)被放入meta字段中。
createAction(
'FETCH_POSTS',
fetch(`url`)
.then(response => response.json())
)
在上面的代碼中我們將一個(gè)網(wǎng)絡(luò)請(qǐng)求promise作為參數(shù)進(jìn)行傳遞萧吠。
Reducer
當(dāng)我們確定了組件的state對(duì)象結(jié)構(gòu)和action行為的時(shí)候就可以編寫reducer了左冬。reducer的作用就是根據(jù)傳入的Action行為和舊的state對(duì)象,返回一個(gè)新的state并刷新組件纸型。
const initialState = {
isLoggedIn: false,
};
function user(state = initialState, action) {
if(action.type === 'LOGGED_IN') {
let {username, password} = action.data;
return {
...state,
isLoggedIn: true,
username,
password,
};
}
return state;
}
export default user;
這里模擬了一個(gè)簡(jiǎn)單的情況拇砰,當(dāng)用戶登錄成功后發(fā)出一個(gè)action,reducer收到后返回新的state狀態(tài)并刷新頁面狰腌。
當(dāng)然我們應(yīng)用可能有多個(gè)reducer的情況, 通過combineReducer可以將多個(gè)reducer合成一個(gè)除破。
import {combineReducers} from 'redux';
import user from './user';
import movieList from './movieList';
module.exports = combineReducers({
user,
movieList,
});
reducer的一個(gè)重要特征就是純函數(shù),也就是同樣的輸入琼腔,必須有同樣的輸出瑰枫,有三個(gè)約束需要注意:
*修改傳入?yún)?shù)。
*執(zhí)行有副作用的操作丹莲,如 API 請(qǐng)求和路由跳轉(zhuǎn)光坝。
*調(diào)用非純函數(shù)尸诽,如 Date.now() 或Math.random(), 因?yàn)槊看螘?huì)得到不同的結(jié)果。
也就是說傳入的state如果和舊的state沒有變化盯另,返回的新state也應(yīng)該是一模一樣的性含,不應(yīng)該有沒有任何改變。
store
當(dāng)reducer返回了新的state狀態(tài)后土铺,這個(gè)狀態(tài)怎么傳到組件和存在哪里就成了問題胶滋。
redux就是把這些狀態(tài)統(tǒng)一放入了store進(jìn)行管理。
import { createStore } from 'redux';
const store = createStore(reducers);
這段代碼創(chuàng)建了一個(gè)store并將我們前面合并的reducers注冊(cè)到store中悲敷。
stroe也提供了一些方法供我們調(diào)用:
// 執(zhí)行action究恤, 會(huì)根據(jù)你注冊(cè)的reducer來返回新的state
stroe.disptch(action)
// 注冊(cè)監(jiān)聽器,每當(dāng)action執(zhí)行的時(shí)候就會(huì)被調(diào)用后德,這個(gè)方法比較偏底層部宿,我們一般不會(huì)用到
stroe.subscribe(listener)
// 替換當(dāng)前state中的reducer
stroe.replaceReducer(nextReducer)
流程圖
了解這些我們就能通過發(fā)送Action執(zhí)行一個(gè)大概的流程了: