一,簡介
Redux 是 JavaScript 應(yīng)用的狀態(tài)容器,提供可預(yù)測的狀態(tài)管理。
它主要的幾個方法如下:
重要的有方法 有 dispatch(分發(fā)action)
、getState(獲取state)
、subscribe(監(jiān)聽state的變化)
,下面會介紹到,另外兩個可以不用管;
那什么時候使用Redux呢?
當(dāng)遇到如下問題時,建議開始使用 Redux
:
- 你有很多數(shù)據(jù)隨時間而變化
- 你希望狀態(tài)有一個唯一確定的來源(single source of truth)
- 你發(fā)現(xiàn)將所有狀態(tài)放在頂層組件中管理已不可維護(hù)
二,安裝
我這里安裝的是 "redux": "^4.2.1"
版本;
npm install redux --save
項(xiàng)目的src目錄下面新建store文件夾
和index.js,reducer.js
;如下:
三,三大核心概念Store、Action、Reducer
3.1 Store
Store:存儲數(shù)據(jù)的地方。最好整個應(yīng)用只有一個 Store。
createStore()
:用來生成 Store。接收 Reducer 作為其參數(shù)。
index.js
/**
* 引入createStore 專門創(chuàng)建最為核心的store對象
* 目前createStore已經(jīng)棄用,所以我們要引用legacy_createStore
*/
iimport { legacy_createStore } from "redux";
import reducer from './reducer.ts'
// 創(chuàng)建數(shù)據(jù)倉庫 引入reducer函數(shù)進(jìn)行對數(shù)據(jù)的處理
const store = legacy_createStore(reducer)
export default store
3.2 Reducer
reduce的本質(zhì)就是一個函數(shù) ,作用是初始化狀態(tài)和加工狀態(tài)。
reduce函數(shù)里面接收兩個參數(shù),第一個參數(shù)是state的初始值,第二個參數(shù)是一個action對象,對象里的第一個屬性是type
也就是函數(shù)的名稱,第二個屬性就是傳進(jìn)來的值,用于后續(xù)更改state;
reducer.ts
// 約束類型
interface Eula {
name: string;
age: number;
}
// 定義數(shù)據(jù)
const defaultState: Eula = {
name: "Eula",
age: 18
};
// reducer 函數(shù) 用于更改數(shù)據(jù)
let reducer = (preState = defaultState, action: { type: string; data: number }) => {
// action解構(gòu)出來
let { type, data } = action;
// 第一種寫法 每個分支使用return進(jìn)行返回
// switch (type) {
// case "update_age":
// preState.age = data;
// return preState;
// case "add_age":
// preState.age++;
// return preState;
// case "del_age":
// preState.age--;
// return preState;
// default:
// return preState; // 初始化時
// }
// 第二種寫法 break 與最終的return返回結(jié)果
switch (type) {
case "update_age":
preState.age = data;
break;
case "add_age":
preState.age++;
break;
case "del_age":
preState.age--;
break;
default:
preState; // 初始化時
}
return preState; // 此處 一定要使用return進(jìn)行返回最終改變的值
};
export default reducer;
注意: 初次加載 Store 會自動調(diào)用一次 Reducer 進(jìn)行初始化狀態(tài),此時 state 是 undefined,action 對象中的 type 為 @@redux/INITxxx
。手動調(diào)用 store.dispatch()
也會觸發(fā) Reducer 的自動執(zhí)行。
3.3 Action
Action 就是一個普通的 JS 對象,用于描述要更新的數(shù)據(jù)類型和內(nèi)容,其中 type 屬性是必須的,表示 Action 的名稱,其他屬性可以自由設(shè)置。
redux.tsx
// 引入store
import store from "../../../store/index";
// 更改數(shù)據(jù)時調(diào)用
store.dispatch({ type: "update_age", data: 100 });
store.dispatch()
:所有數(shù)據(jù)的變化,必須通過派發(fā)(dispatch) Action 來更新。接受一個 Action 對象作為參數(shù),將其發(fā)送出去。
四,開始函數(shù)式組件中使用
redux.tsx
import React, { useState } from "react";
// 1,引入store
import store from "../../../store/index";
// 渲染數(shù)據(jù)
const myList:[] = [];
const Redux: React.FC = () => {
let [list, setList] = useState(myList);
console.log("store:", store);
// 監(jiān)聽數(shù)據(jù)的變化
const unsubscribe = store.subscribe(() => {
console.log("訂閱數(shù)據(jù)的變化", store.getState());
// 此處用來觸發(fā)視圖的更新
setList([]);
});
// 改變store中的數(shù)據(jù)
const update = () => {
store.dispatch({ type: "update_age", data: 100 });
};
const add = () => {
store.dispatch({ type: "add_age" });
};
const del = () => {
store.dispatch({ type: "del_age" });
};
// 此處才是真正渲染的頁面
return (
<div className="redux">
<h3>redux演示</h3>
<button onClick={update}>更改store的數(shù)據(jù)+100</button>
<button onClick={add}>更改store的數(shù)據(jù)++</button>
<button onClick={del}>更改store的數(shù)據(jù)--</button>
<p>store的num數(shù)據(jù):{store.getState().age}</p>
</div>
);
};
export default Redux;
效果圖:
上面的組件是一個簡單的案例演示,定義了三個點(diǎn)擊事件,點(diǎn)擊第一個按鈕state.age+100
,點(diǎn)擊第二個按鈕每次state.age+1
,點(diǎn)擊第三個按鈕age每次減一;下面會詳細(xì)介紹幾個重點(diǎn)內(nèi)容:
4.1,引入store
先引進(jìn)來,這個沒什么好說的;
import store from "../../../store/index";
4.1,store.getState()方法
getState()
方法是redux實(shí)例下的方法之一,上面的第一張截圖已經(jīng)通過store實(shí)例打印出來了;
getState()
的作用是獲取當(dāng)前狀態(tài)下運(yùn)行在redux中的state;也就是說獲取store中最新的數(shù)據(jù);
<p>store的num數(shù)據(jù):{store.getState().age}</p>
4.3,store.dispatch()方法
dispatch()
是唯一能夠修改 state 數(shù)據(jù)的行為。通過分發(fā)action
(其實(shí)就是一個對象),配合 dispatch 函數(shù)傳入的 action 及其 payload 計(jì)算得到新的 state,并更新到閉包數(shù)據(jù)中,這樣就實(shí)現(xiàn)了 state 的更新;
如下:
reducer.tsx
// 改變store中的數(shù)據(jù)
const update = () => {
store.dispatch({ type: "update_age", data: 100 });
};
const add = () => {
store.dispatch({ type: "add_age" });
};
const del = () => {
store.dispatch({ type: "del_age" });
};
上面的代碼會和下面的 switch case
表達(dá)式所判斷的type
要一 一對應(yīng),用于更新state;
reducer.ts
let reducer = (preState = defaultState, action: { type: string; data: number }) => {
let { type, data } = action;
// 第一種寫法 每個分支使用return進(jìn)行返回
// switch (type) {
// case "update_age":
// preState.age = data;
// return preState;
// case "add_age":
// preState.age++;
// return preState;
// case "del_age":
// preState.age--;
// return preState;
// default:
// return preState; // 初始化時
// }
// 第二種寫法 break 與最終的return返回結(jié)果
switch (type) {
case "update_age":
preState.age = data;
break;
case "add_age":
preState.age++;
break;
case "del_age":
preState.age--;
break;
default:
preState; // 初始化時
}
return preState; // 此處 一定要使用return進(jìn)行返回最終改變的值
};
上面的兩種寫法是一樣的;對比一下;
4.4,store.subscribe()方法
subscribe
函數(shù)只要store中的state數(shù)據(jù)變化了,就會觸發(fā)subscribe
方法,相當(dāng)注冊了一個監(jiān)聽器;監(jiān)聽store中的數(shù)據(jù)變化;
從 react 層面來說,redux 的 store 是隔離開的,我們需要一個橋梁,使得數(shù)據(jù)層出現(xiàn)更新的同時更新UI層邏輯,這時 store 中的最后一個方法,subscribe 方法就派上用場了。
注意: setList([])
:是為了主動觸發(fā)react視圖更新的方法,否則store中數(shù)據(jù)改變了,視圖卻沒有重新渲染。
import React, { useState } from "react";
const Redux: React.FC = () => {
let [list, setList] = useState(myList);
// 監(jiān)聽數(shù)據(jù)的變化
const unsubscribe = store.subscribe(() => {
console.log("訂閱數(shù)據(jù)的變化", store.getState());
// 此處用來觸發(fā)視圖的更新
setList([]);
});
}
subscribe
也同時返回了一個 unsubscribe 函數(shù)。當(dāng)我們不在希望訂閱這個監(jiān)聽器時,調(diào)用 unsubscribe()
,對應(yīng)的函數(shù)就會從監(jiān)聽器隊(duì)列中被移除。
unsubscrib() // 不再監(jiān)聽
五,Redux 的三大原則
- 單一數(shù)據(jù)源:整個應(yīng)用程序的 State 被存儲在一棵 object tree 中,并且這棵 object tree 只存儲在一個 Store 中。單一數(shù)據(jù)源可以讓整個應(yīng)用程序的 State 變得方便維護(hù)、修改、追蹤。
- State 是只讀的:唯一修改 State 的方法就是觸發(fā) Action,不要試圖在其他地方通過任何的方式來修改State。這樣可以保證所有的修改都被集中化處理,并且按照嚴(yán)格的順序來執(zhí)行。
- 使用純函數(shù)來執(zhí)行修改:通過 Reducer 將舊的 State 和 Action 聯(lián)系在一起,返回一個新的 State。所有的Reducer 都應(yīng)該是純函數(shù),不能產(chǎn)生任何的副作用。
End:文章來源:http://www.zghlxwxcb.cn/news/detail-639528.html
[redux中文網(wǎng)]: https://cn.redux.js.org/文章來源地址http://www.zghlxwxcb.cn/news/detail-639528.html
到了這里,關(guān)于Redux - Redux在React函數(shù)式組件中的基本使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!