一、react-redux介紹
- 官網(wǎng)地址
React 和 Redux 是兩個(gè)獨(dú)立的庫(kù),兩者之間職責(zé)獨(dú)立。因此,為了實(shí)現(xiàn)在 React 中使用 Redux 進(jìn)行狀態(tài)管理 ,就需要一種機(jī)制,將這兩個(gè)獨(dú)立的庫(kù)關(guān)聯(lián)在一起。這時(shí)候就用到 React-Redux 這個(gè)綁定庫(kù)了
作用:為 React 接入 Redux,實(shí)現(xiàn)在 React 中使用 Redux 進(jìn)行狀態(tài)管理。
react-redux 庫(kù)是 Redux 官方提供的 React 綁定庫(kù)。
二、React-Redux-基本使用
react-redux 的使用分為兩大步:1 全局配置(只需要配置一次) 2 組件接入(獲取狀態(tài)或修改狀態(tài))
-
全局配置
1.安裝 react-redux:npm i react-redux
2.從 react-redux 中導(dǎo)入 Provider 組件
3.導(dǎo)入創(chuàng)建好的 redux 倉(cāng)庫(kù)
4.使用 Provider 包裹整個(gè)應(yīng)用
5.將導(dǎo)入的 store 設(shè)置為 Provider 的 store 屬性值
index.js 核心代碼
// 導(dǎo)入 Provider 組件
import { Provider } from 'react-redux'
// 導(dǎo)入創(chuàng)建好的 store
import store from './store'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.querySelector('#root')
)
三、獲取狀態(tài)useSelector
-
useSelector:獲取 Redux 提供的狀態(tài)數(shù)據(jù)
-
參數(shù):selector 函數(shù),用于從 Redux 狀態(tài)中篩選出需要的狀態(tài)數(shù)據(jù)并返回
-
返回值:篩選出的狀態(tài)
import { useSelector } from 'react-redux'
// 計(jì)數(shù)器案例中,Redux 中的狀態(tài)是數(shù)值,所以,可以直接返回 state 本身
const count = useSelector(state => state)
// 比如,Redux 中的狀態(tài)是個(gè)對(duì)象,就可以:
const list = useSelector(state => state.list)
App.js中核心代碼
import { useSelector } from 'react-redux'
const App = () => {
const count = useSelector(state => state)
return (
<div>
<h1>計(jì)數(shù)器:{count}</h1>
<button>數(shù)值增加</button>
<button>數(shù)值減少</button>
</div>
)
}
四、分發(fā)動(dòng)作useDispatch
useDispatch:拿到 dispatch 函數(shù),分發(fā) action,修改 redux 中的狀態(tài)數(shù)據(jù)
語(yǔ)法
import { useDispatch } from 'react-redux'
// 調(diào)用 useDispatch hook,拿到 dispatch 函數(shù)
const dispatch = useDispatch()
// 調(diào)用 dispatch 傳入 action,來(lái)分發(fā)動(dòng)作
dispatch( action )
App.js 中核心代碼
import { useDispatch } from 'react-redux'
const App = () => {
const dispatch = useDispatch()
return (
<div>
<h1>計(jì)數(shù)器:{count}</h1>
{/* 調(diào)用 dispatch 分發(fā) action */}
<button onClick={() => dispatch(increment(2))}>數(shù)值增加</button>
<button onClick={() => dispatch(decrement(5))}>數(shù)值減少</button>
</div>
)
}
五、 Redux 數(shù)據(jù)流
任何一個(gè)組件都可以直接接入 Redux,也就是可以直接:1 修改 Redux 狀態(tài) 2 接收 Redux 狀態(tài)
并且,只要 Redux 中的狀態(tài)改變了,所有接收該狀態(tài)的組件都會(huì)收到通知,也就是可以獲取到最新的 Redux 狀態(tài)
跨組件可直接通訊
六、代碼結(jié)構(gòu)
在使用 Redux 進(jìn)行項(xiàng)目開(kāi)發(fā)時(shí),不會(huì)將 action/reducer/store 都放在同一個(gè)文件中,而是會(huì)進(jìn)行拆分
可以按照以下結(jié)構(gòu),來(lái)組織 Redux 的代碼:
/store --- 在 src 目錄中創(chuàng)建,用于存放 Redux 相關(guān)的代碼
/actions.js --- 存放所有的 action
/reducers.js --- 存放所有的 reducer
index.js --- redux 的入口文件,用來(lái)創(chuàng)建 store
示例actions.js
export const AddMoney = (money) => ({ type: 'add_money', money })
export const SubMoney = (money) => ({ type: 'sub_money', money })
示例reducers.js
export default function reducer(state = 1000, action) {
if (action.type === 'add_money') {
return state + action.money
}
if (action.type === 'sub_money') {
return state - action.money
}
return state
}
示例index.js
//createStore 方法已被啟用
import { legacy_createStore as createStore } from 'redux'
import reducer from './reducer'
console.log('reducer', reducer)
const store = createStore(reducer)
export default store
七、ActionType的使用
Action Type 指的是:action 對(duì)象中 type 屬性的值
Redux 項(xiàng)目中會(huì)多次使用 action type,比如,action 對(duì)象、reducer 函數(shù)、dispatch(action) 等
目標(biāo):集中處理 action type,保持項(xiàng)目中 action type 的一致性
-
action type 的值采用:'domain/action'(功能/動(dòng)作)形式,進(jìn)行分類(lèi)處理,比如,
計(jì)數(shù)器:'counter/increment' 表示 Counter 功能中的 increment 動(dòng)作
登錄:'login/getCode' 表示登錄獲取驗(yàn)證碼的動(dòng)作
個(gè)人資料:'profile/get' 表示獲取個(gè)人資料
步驟
1.在 store 目錄中創(chuàng)建 actionTypes 目錄或者 constants 目錄,集中處理
2.創(chuàng)建常量來(lái)存儲(chǔ) action type,并導(dǎo)出
3.將項(xiàng)目中用到 action type 的地方替換為這些常量,從而保持項(xiàng)目中 action type 的一致性
核心代碼
// actionTypes 或 constants 目錄:
const increment = 'counter/increment'
const decrement = 'counter/decrement'
export { increment, decrement }
// --
// 使用:
// actions/index.js
import * as types from '../acitonTypes'
const increment = payload => ({ type: types.increment, payload })
const decrement = payload => ({ type: types.decrement, payload })
// reducers/index.js
import * as types from '../acitonTypes'
const reducer = (state, action) => {
switch (action.type) {
case types.increment:
return state + 1
case types.decrement:
return state - action.payload
default:
return state
}
}
注:額外添加 Action Type 會(huì)讓項(xiàng)目結(jié)構(gòu)變復(fù)雜,此操作可省略。但,domain/action 命名方式強(qiáng)烈推薦!
八、Reducer的分離與合并
隨著項(xiàng)目功能變得越來(lái)越復(fù)雜,需要 Redux 管理的狀態(tài)也會(huì)越來(lái)越多
-
此時(shí),有兩種方式來(lái)處理狀態(tài)的更新
1.使用一個(gè) reducer:處理項(xiàng)目中所有狀態(tài)的更新
2.用多個(gè) reducer:按照項(xiàng)目功能劃分,每個(gè)功能使用一個(gè) reducer 來(lái)處理該功能的狀態(tài)更新
推薦:使用多個(gè) reducer(第二種方案),每個(gè) reducer 處理的狀態(tài)更單一,職責(zé)更明確
此時(shí),項(xiàng)目中會(huì)有多個(gè) reducer,但是 store 只能接收一個(gè) reducer,因此,需要將多個(gè) reducer 合并為一根 reducer,才能傳遞給 store
合并方式:使用 Redux 中的 combineReducers 函數(shù)
注意:合并后,Redux 的狀態(tài)會(huì)變?yōu)橐粋€(gè)對(duì)象,對(duì)象的結(jié)構(gòu)與 combineReducers 函數(shù)的參數(shù)結(jié)構(gòu)相同
核心代碼
import { combineReducers } from 'redux'
// 計(jì)數(shù)器案例,狀態(tài)默認(rèn)值為:0
const aReducer = (state = 0, action) => {}
// Todos 案例,狀態(tài)默認(rèn)值為:[]
const bReducer = (state = [], action) => {}
// 合并多個(gè) reducer 為一個(gè) 根reducer
const rootReducer = combineReducers({
a: aReducer,
b: bReducer
})
// 創(chuàng)建 store 時(shí),傳入 根reducer
const store = createStore(rootReducer)
// 此時(shí),合并后的 redux 狀態(tài): { a: 0, b: [] }
九、購(gòu)物掙錢(qián)案例
基本結(jié)構(gòu) 跟組件下包含兩個(gè)子組件
實(shí)現(xiàn)功能 點(diǎn)擊子組件對(duì)應(yīng)的按鈕 實(shí)現(xiàn)根組件 兄弟組件資金的更改
-
需安裝react-redux 和 redux
代碼基本目錄
index.js 代碼
import ReactDom from 'react-dom/client'
import App from './App'
//引入Provider
import { Provider } from 'react-redux'
//引入store
import store from './store/index'
ReactDom.createRoot(document.querySelector('#root')).render(
<Provider store={store}>
<App></App>
</Provider>
)
App.js代碼
import Women from './components/women'
import Man from './components/man'
//引入useSelector
import { useSelector } from 'react-redux'
export default function App() {
const money = useSelector((state) => {
return state.money
})
return (
<div>
<h1>我是根組件</h1>
<div>資金:{money}</div>
<Women></Women>
<Man></Man>
</div>
)
}
women組件
//引入 useSelector, useDispatch
import { useSelector, useDispatch } from 'react-redux'
//引入 action下的SubMoney
import { SubMoney } from '../store/action'
export default function Man() {
const money = useSelector((state) => state.money)
const dispath = useDispatch()
return (
<div>
<h3>女人組件</h3>
<div>金錢(qián):{money}</div>
<button
onClick={() => {
dispath(SubMoney(500))
}}
>
買(mǎi)包-500
</button>
</div>
)
}
men組件
//引入 useSelector, useDispatch
import { useSelector, useDispatch } from 'react-redux'
//引入action下的 AddMoney
import { AddMoney } from '../store/action'
export default function Women() {
const money = useSelector((state) => state.money)
const dispath = useDispatch()
return (
<div>
<h3>男人組件</h3>
<div>金錢(qián):{money}</div>
<button onClick={() => dispath(AddMoney(10))}>搬磚 + 10</button>
<button onClick={() => dispath(AddMoney(10000))}>賣(mài)腎 + 10000</button>
</div>
)
}
store文件下的action.js 代碼
//按需導(dǎo)出
export const AddMoney = (money) => ({ type: 'add_money', money })
export const SubMoney = (money) => ({ type: 'sub_money', money })
store文件下的reducer.js 代碼文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-670303.html
//引入 combineReducers
import { combineReducers } from 'redux'
//user模塊
function user(state = { name: '張三', age: '20歲' }, action) {
return state
}
//money 模塊
function money(state = 1000, action) {
if (action.type === 'add_money') {
return state + action.money
}
if (action.type === 'sub_money') {
return state - action.money
}
return state
}
//模塊化
const rootReducer = combineReducers({
user,
money,
})
console.log('導(dǎo)出', rootReducer)
export default rootReducer
store文件下的index.js 代碼文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-670303.html
//createStore 方法已被啟用
import { legacy_createStore as createStore } from 'redux'
import reducer from './reducer'
console.log('reducer', reducer)
const store = createStore(reducer)
export default store
到了這里,關(guān)于react之react-redux的介紹、基本使用、獲取狀態(tài)、分發(fā)動(dòng)作、數(shù)據(jù)流、reducer的分離與合并等的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!