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 對應的 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ù)組展開并應用到 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是同步的操作。當你調用 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ù),不應該包含任何副作用,如異步操作、網(wǎng)絡請求等。
四、middleware中間件
1、常用中間件 redux-thunk
redux-thunk
是一個 Redux 中間件,它允許你在 action creators 中返回函數(shù)而不僅僅是普通的 action 對象。
這個函數(shù)可以用于處理異步操作,如發(fā)起網(wǎng)絡請求、定時器、以及其他需要延遲執(zhí)行的操作。
在 Redux 中,普通的 action 必須是一個普通的對象,包含一個 type 屬性來描述操作的類型。
但有些情況下,我們需要在 action creators 中執(zhí)行異步操作,例如從服務器獲取數(shù)據(jù),然后再將相應的數(shù)據(jù)分發(fā)到 Redux Store 中。
這就是 redux-thunk 發(fā)揮作用的地方。
redux-thunk 的主要功能是攔截分發(fā)的 action,dispatch中可以接受對象也可以接受函數(shù),并判斷 action 是一個普通的對象還是一個函數(shù)。
如果是一個函數(shù), redux-thunk 會將 dispatch 和 getState 函數(shù)傳遞給這個函數(shù),使得你可以在函數(shù)內部執(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ù)將請求結果傳遞給 Redux store
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
});
};
}
store.dispatch(fetchData()); // 分發(fā)異步 actionredux-saga
創(chuàng)建一個 Saga,它是一個 Generator 函數(shù),用于處理特定的異步操作。
Saga 監(jiān)聽 action 并執(zhí)行相應的邏輯。
你可以在 Saga 中執(zhí)行異步操作,如網(wǎng)絡請求、定時器等。
// 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();
每當你調用 action creator 時, redux-logger 會在瀏覽器控制臺中輸出相應的日志,顯示 action 的類型、舊狀態(tài)、新狀態(tài)等信息。
總之, redux-logger 是一個方便的中間件,用于在開發(fā)環(huán)境中輸出有關 Redux 操作的日志,以幫助你更好地理解應用程序的狀態(tài)變化。
2、自定義中間件
重要的入?yún)ⅲ簊tore、next、action
next 是一個函數(shù),用于將 action 繼續(xù)傳遞給下一個中間件或最終到達 reducer。
在中間件函數(shù)中,你可以執(zhí)行一些邏輯,然后調用 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)變化的方法。
它允許你注冊一個回調函數(shù),當 Redux Store 中的狀態(tài)發(fā)生變化時,這個回調函數(shù)會被調用,從而你可以執(zhí)行一些操作來響應狀態(tài)的變化。
具體來說, subscribe 方法的作用是將一個函數(shù)添加到狀態(tài)變化的監(jiān)聽器列表中,每當狀態(tài)發(fā)生變化時,所有訂閱了這個監(jiān)聽器的函數(shù)都會被調用。
這樣,你可以在狀態(tài)變化時更新用戶界面、執(zhí)行特定操作等。
store.subscribe(() => console.log(store.getState()))
在上面的例子中, store.subscribe() 方法用于注冊一個監(jiān)聽器,每當狀態(tài)發(fā)生變化時,回調函數(shù)會被調用并輸出當前的狀態(tài)。通過調用 unsubscribe() 方法,可以取消訂閱狀態(tài)變化,以避免不再需要的監(jiān)聽器持續(xù)執(zhí)行。
總而言之, subscribe 方法在 Redux 中用于監(jiān)聽狀態(tài)的變化,以便你可以在狀態(tài)更新時執(zhí)行相應的操作,如更新界面或觸發(fā)其他邏輯。
2、connect
connect 是 React Redux 庫提供的一個高階函數(shù)(Higher-Order Function),用于連接 React 組件與 Redux Store。它的作用是將 Redux 的狀態(tài)(state)和操作(actions)與 React 組件進行關聯(lián),使得組件能夠訪問 Redux 中的狀態(tài)并調用相應的操作來更新狀態(tài)。
使用 connect 方法,你可以將 Redux Store 中的狀態(tài)映射到組件的 props 上,以便在組件內部可以直接訪問這些狀態(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ù),然后返回一個對象,這個對象中的鍵值對通常是調用 Action Creators 后返回的 action 對象。這樣,組件就可以通過 props 調用這些操作來分發(fā) action。
通過 connect 方法,你可以實現(xiàn)將 Redux 的狀態(tài)和操作傳遞給組件,使得組件能夠與 Redux Store 進行交互。這大大簡化了組件與狀態(tài)管理之間的關系,提高了代碼的可維護性和可擴展性。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
react ant protable自定義實現(xiàn)搜索下拉框
這篇文章主要介紹了react ant protable自定義實現(xiàn)搜索下拉框,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
詳解Stack?Navigator中使用自定義的Render?Callback
這篇文章主要為大家介紹了Stack?Navigator中使用自定義的Render?Callback使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10

