Redux使用方法和基本原理解讀
一、redux core和redux tookit
1、區(qū)別
redux core是最原生的redux概念,其優(yōu)點是可定制性好,缺點是什么都要自己寫。主要思想是通過傳入createStore,將actions、reducers、middlewares等進行自己配置。
redux toolkit其實是去包裹一個redux core的工具集,引入了一些簡化的 API去配置redux store。同時Redux Toolkit 中的 createSlice 自動生成了每個 reducer case 對應(yīng)的 action creators,免去了手動編寫 action creators 的繁瑣步驟。不僅如此,redux toolkit還默認集成了redux-thunk中間件。避免了每次都要手動配置。
2、基本配置和使用
1、redux core
基本api:
createStore
:創(chuàng)建一個redux storecombineReducers
:合并多個reducerapplyMiddleware:
傳入中間件compose
:合并多個store
當你配置某個store在store.js文件中、reducer定義在reducers.js文件中、并且引入一些middleware時,配置方法大致為:
//store.js import { createStore, applyMiddleware } from 'redux'; import rootReducer from './reducers'; import thunkMiddleware from 'redux-thunk'; // Redux Thunk 中間件 import loggerMiddleware from 'redux-logger'; // Redux Logger 中間件 const middlewares = [thunkMiddleware, loggerMiddleware]; // 定義要使用的中間件數(shù)組 const store = createStore( rootReducer, applyMiddleware(...middlewares) // 將中間件數(shù)組展開并應(yīng)用到 Redux Store ); export default store;
//reducers.js import { combineReducers } from 'redux'; import counterReducer from './counterReducer'; import userReducer from './userReducer'; // 合并多個 reducer const rootReducer = combineReducers({ counter: counterReducer, user: userReducer }); export default rootReducer;
//counterReducer.js export function counterReducer(state = { value: 0 }, action) { switch (action.type) { case 'counter/incremented': return { value: state.value + 1 } case 'counter/decremented': return { value: state.value - 1 } default: return state } } //dispatch傳入action對象 //store.dispatch({ type: 'counter/incremented' }) // {value: 1} //store.dispatch({ type: 'counter/incremented' }) // {value: 2} //store.dispatch({ type: 'counter/decremented' })
2、redux toolkit
在slice.js中創(chuàng)建reducers、在store.js中創(chuàng)建store并配置reducers和中間件
//store.js import { configureStore } from '@reduxjs/toolkit' import todosReducer from '../features/todos/todosSlice' import filtersReducer from '../features/filters/filtersSlice' export const store = configureStore({ reducer: { todos: todosReducer, filters: filtersReducer } })
在slice中,只需要直接定義reducers操作而無需再對action creators即{type : actions.type}對象做出顯示創(chuàng)建或定義,其放入dispatch中會自動創(chuàng)建、分發(fā)
//slice.js,導出actions和reducers import { createSlice } from '@reduxjs/toolkit' const todosSlice = createSlice({ name: 'todos', initialState: [], reducers: { todoAdded(state, action) { state.push({ id: action.payload.id, text: action.payload.text, completed: false }) }, todoToggled(state, action) { const todo = state.find(todo => todo.id === action.payload) todo.completed = !todo.completed } } }) export const { todoAdded, todoToggled } = todosSlice.actions export default todosSlice.reducer
二、dispatch action修改store
dispatch
是同步的操作。當你調(diào)用 Redux Store 的dispatch
方法分發(fā)一個 action 時,Redux 會立即執(zhí)行 reducer 并更新狀態(tài)。這意味著dispatch
操作本身不會引起異步行為。
在組件中,我們可以用useDispatch hook來獲取到dispatch方法,從而對store進行操作
三、reducer
Reducer 是同步的。
在 Redux 中,Reducer 是一個純函數(shù),負責處理分發(fā)的 action 并更新狀態(tài)。
它是一個純粹的函數(shù),不應(yīng)該包含任何副作用,如異步操作、網(wǎng)絡(luò)請求等。
四、middleware中間件
1、常用中間件 redux-thunk
redux-thunk
是一個 Redux 中間件,它允許你在 action creators 中返回函數(shù)而不僅僅是普通的 action 對象。
這個函數(shù)可以用于處理異步操作,如發(fā)起網(wǎng)絡(luò)請求、定時器、以及其他需要延遲執(zhí)行的操作。
在 Redux 中,普通的 action 必須是一個普通的對象,包含一個 type
屬性來描述操作的類型。
但有些情況下,我們需要在 action creators 中執(zhí)行異步操作,例如從服務(wù)器獲取數(shù)據(jù),然后再將相應(yīng)的數(shù)據(jù)分發(fā)到 Redux Store 中。
這就是 redux-thunk
發(fā)揮作用的地方。
redux-thunk
的主要功能是攔截分發(fā)的 action,dispatch中可以接受對象也可以接受函數(shù),并判斷 action 是一個普通的對象還是一個函數(shù)。
如果是一個函數(shù), redux-thunk
會將 dispatch
和 getState
函數(shù)傳遞給這個函數(shù),使得你可以在函數(shù)內(nèi)部執(zhí)行異步操作,并在操作完成后手動分發(fā)其他 action。
*用法示例:
import { createStore, applyMiddleware } from 'redux'; import thunkMiddleware from 'redux-thunk'; import rootReducer from './reducers'; const store = createStore( rootReducer, applyMiddleware(thunkMiddleware) ); // 異步 action creator function fetchData() { return (dispatch, getState) => { // 獲取當前 Redux store 狀態(tài) const currentState = getState(); // 執(zhí)行異步操作 fetch('https://api.example.com/data') .then(response => response.json()) .then(data => { // 在異步操作完成后使用 dispatch 函數(shù)將請求結(jié)果傳遞給 Redux store dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data }); }); }; } store.dispatch(fetchData()); // 分發(fā)異步 action
redux-saga
創(chuàng)建一個 Saga,它是一個 Generator 函數(shù),用于處理特定的異步操作。
Saga 監(jiān)聽 action 并執(zhí)行相應(yīng)的邏輯。
你可以在 Saga 中執(zhí)行異步操作,如網(wǎng)絡(luò)請求、定時器等。
// sagas.js import { takeEvery, put, call } from 'redux-saga/effects'; import { FETCH_DATA, fetchDataSuccess, fetchDataFailure } from './actions'; function* fetchDataSaga(action) { try { const response = yield call(fetch, 'https://api.example.com/data'); const data = yield call([response, 'json']); yield put(fetchDataSuccess(data)); } catch (error) { yield put(fetchDataFailure(error)); } } export function* rootSaga() { yield takeEvery(FETCH_DATA, fetchDataSaga); }
創(chuàng)建saga middleware放入到store中
// store.js import { createStore, applyMiddleware } from 'redux'; import createSagaMiddleware from 'redux-saga'; import rootReducer from './reducers'; import { rootSaga } from './sagas'; const sagaMiddleware = createSagaMiddleware(); const store = createStore( rootReducer, applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga); export default store;
redux-logger
const loggerMiddleware = createLogger();
每當你調(diào)用 action creator 時, redux-logger
會在瀏覽器控制臺中輸出相應(yīng)的日志,顯示 action 的類型、舊狀態(tài)、新狀態(tài)等信息。
總之, redux-logger
是一個方便的中間件,用于在開發(fā)環(huán)境中輸出有關(guān) Redux 操作的日志,以幫助你更好地理解應(yīng)用程序的狀態(tài)變化。
2、自定義中間件
重要的入?yún)ⅲ簊tore、next、action
next
是一個函數(shù),用于將 action 繼續(xù)傳遞給下一個中間件或最終到達 reducer。
在中間件函數(shù)中,你可以執(zhí)行一些邏輯,然后調(diào)用 next(action)
來將 action 傳遞給下一個中間件或 reducer。
例子:
const myMiddleware = store => next => action => { // 在 action 被分發(fā)到 reducer 前執(zhí)行的邏輯 console.log('Middleware triggered:', action); // 將 action 傳遞給下一個中間件或 reducer const result = next(action); // 在 action 被分發(fā)到 reducer 后執(zhí)行的邏輯 console.log('Middleware completed:', action); return result; };
五、一些其他常用方法:(subscribe、connect等等)
1、subscribe
在 Redux 中, subscribe
是一個用于訂閱狀態(tài)變化的方法。
它允許你注冊一個回調(diào)函數(shù),當 Redux Store 中的狀態(tài)發(fā)生變化時,這個回調(diào)函數(shù)會被調(diào)用,從而你可以執(zhí)行一些操作來響應(yīng)狀態(tài)的變化。
具體來說, subscribe
方法的作用是將一個函數(shù)添加到狀態(tài)變化的監(jiān)聽器列表中,每當狀態(tài)發(fā)生變化時,所有訂閱了這個監(jiān)聽器的函數(shù)都會被調(diào)用。
這樣,你可以在狀態(tài)變化時更新用戶界面、執(zhí)行特定操作等。
store.subscribe(() => console.log(store.getState()))
在上面的例子中, store.subscribe()
方法用于注冊一個監(jiān)聽器,每當狀態(tài)發(fā)生變化時,回調(diào)函數(shù)會被調(diào)用并輸出當前的狀態(tài)。通過調(diào)用 unsubscribe()
方法,可以取消訂閱狀態(tài)變化,以避免不再需要的監(jiān)聽器持續(xù)執(zhí)行。
總而言之, subscribe
方法在 Redux 中用于監(jiān)聽狀態(tài)的變化,以便你可以在狀態(tài)更新時執(zhí)行相應(yīng)的操作,如更新界面或觸發(fā)其他邏輯。
2、connect
connect
是 React Redux 庫提供的一個高階函數(shù)(Higher-Order Function),用于連接 React 組件與 Redux Store。它的作用是將 Redux 的狀態(tài)(state)和操作(actions)與 React 組件進行關(guān)聯(lián),使得組件能夠訪問 Redux 中的狀態(tài)并調(diào)用相應(yīng)的操作來更新狀態(tài)。
使用 connect
方法,你可以將 Redux Store 中的狀態(tài)映射到組件的 props 上,以便在組件內(nèi)部可以直接訪問這些狀態(tài)。同時,你也可以將 Redux 的 Action Creators 映射到組件的 props 上,使得組件可以觸發(fā)這些操作來分發(fā) action,從而更新 Redux Store 的狀態(tài)。
connect
方法的基本語法如下:
import { connect } from 'react-redux'; // Connect the component to Redux const ConnectedComponent = connect(mapStateToProps, mapDispatchToProps)(Component);
其中, mapStateToProps
和 mapDispatchToProps
是兩個函數(shù),用于定義如何將 Redux 的狀態(tài)和操作映射到組件的 props 上。它們的作用分別如下:
mapStateToProps(state, ownProps)
:這個函數(shù)用于將 Redux 的狀態(tài)映射到組件的 props 上。它接收當前的 Redux 狀態(tài)作為參數(shù),然后返回一個對象,這個對象中的鍵值對會成為組件的 props。這樣,組件就可以通過 props 直接訪問 Redux 中的狀態(tài)。mapDispatchToProps(dispatch, ownProps)
:這個函數(shù)用于將 Redux 的 Action Creators 映射到組件的 props 上。它接收 Redux 的dispatch
方法作為參數(shù),然后返回一個對象,這個對象中的鍵值對通常是調(diào)用 Action Creators 后返回的 action 對象。這樣,組件就可以通過 props 調(diào)用這些操作來分發(fā) action。
通過 connect
方法,你可以實現(xiàn)將 Redux 的狀態(tài)和操作傳遞給組件,使得組件能夠與 Redux Store 進行交互。這大大簡化了組件與狀態(tài)管理之間的關(guān)系,提高了代碼的可維護性和可擴展性。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
react ant protable自定義實現(xiàn)搜索下拉框
這篇文章主要介紹了react ant protable自定義實現(xiàn)搜索下拉框,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06react-native中路由頁面的跳轉(zhuǎn)與傳參的實例詳解
這篇文章主要介紹了react-native中路由頁面的跳轉(zhuǎn)與傳參,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08詳解Stack?Navigator中使用自定義的Render?Callback
這篇文章主要為大家介紹了Stack?Navigator中使用自定義的Render?Callback使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10