Redux 使用及基本原理

什么是Redux

Redux 是用于js應用的狀態管理庫,通常和React一起用。幫助開發者管理應用中各個組件之間的狀態,使得狀態的變化變得更加可預測和易于調試。
Redu也可以不和React組合使用。(通常一起使用)

Redux 三大原則

單一數據源

  • 整個應用程序的state被存儲在一棵obj tree中,這個obj tree只存儲在一個store中;
  • redux 并沒有強制讓我們不能創建多個Store,但這樣做不利于數據的維護;
  • 單一的數據源可以讓整個應用程序的state變得方便維護,追蹤,修改。

State是只讀的

  • 唯一修改state的方法是觸發action
  • 這樣確保了View或網絡請求都不能直接修改state,他們只能通過action來描述自己想要如何修改state;
  • 可以保證所有修改都被集中化處理,并按照嚴格的順序來執行,所以不必擔心race condition的問題。

使用純函數來執行修改

  • 通過reducer將舊state和actions聯系在一起,返回一個新的State
  • 隨著應用程序的復雜度增加,我們可以將reducer拆分成多個小的reducers,分別操作不同state tree 的一部分
  • 但所有的reducers都應該是純函數,不能產生任何的副作用。
    在這里插入圖片描述

redux 如何使用

  1. 安裝react-redux:
    yarn add react-redux
  2. 創建store 管理全局狀態

src/store/constants.js

export const ADD_NUMBER = 'add_number'
export const SUB_NUMBER = 'sub_number'
export const CHANGE_BANNERS = 'change_banners'
export const CHANGE_RECOMMENDS = 'change_recommends'

創建reducer管理狀態

src/store/reducers.js

import * as actionTypes from "./constants"const initialState = {counter: 100,banners: [],recommends: []
}
function reducer(state = initialState, action) {switch (action.type) {case actionTypes.ADD_NUMBER:return { ...state, counter: state.counter + action.num }case actionTypes.SUB_NUMBER:return { ...state, counter: state.counter - action.num }case actionTypes.CHANGE_BANNERS:return { ...state, banners: action.banners }case actionTypes.CHANGE_RECOMMENDS:return { ...state, recommends: action.recommends }default:return state}
}
export default reducer

src/store/index.js

import { createStore } from 'redux';
import reducer from './reducer';const store = createStore(reducer);export default store;

src/store/actionCreators.js
創建actionCreators,放修改狀態的函數

import * as actionTypes from "./constants"
import axios from "axios"export const addNumberAction = (num) => ({type: actionTypes.ADD_NUMBER,num
})export const subNumberAction = (num) => ({type: actionTypes.SUB_NUMBER,num
})export const changeBannersAction = (banners) => ({type: actionTypes.CHANGE_BANNERS,banners
})export const changeRecommendsAction = (recommends) => ({type: actionTypes.CHANGE_RECOMMENDS,recommends
})export const fetchHomeMultidataAction = () => {// 如果是一個普通的action, 那么我們這里需要返回action對象// 問題: 對象中是不能直接拿到從服務器請求的異步數據的// return {}return function(dispatch, getState) {// 異步操作: 網絡請求// console.log("foo function execution-----", getState().counter)axios.get("http://123.207.32.32:8000/home/multidata").then(res => {const banners = res.data.data.banner.listconst recommends = res.data.data.recommend.list// dispatch({ type: actionTypes.CHANGE_BANNERS, banners })// dispatch({ type: actionTypes.CHANGE_RECOMMENDS, recommends })dispatch(changeBannersAction(banners))dispatch(changeRecommendsAction(recommends))})}// 如果返回的是一個函數, 那么redux是不支持的// return foo
}
  1. 在項目index.js 根節點引用
    src/index.js
import {Provider} from 'react-redux'
import store from 'react-redux'const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>
);
  1. 在需要使用redux的頁面或組件中,通過connect高階組件映射到該組件的props中,解耦store和class組件的耦合。
    在這里插入圖片描述

redux中異步操作

redux也引入了中間件的概念:

  • 目的是在dispatch的action和最終達到的reducer之間,擴展一些自己的代碼
  • 比如日志記錄,調用異步接口,添加代碼調試功能等

發送異步網絡請求,可以添加對應的中間件

  • 官網推薦 redux-thunk

redux-thunk 如何可以發送異步請求

  • 默認情況下的dispatch(action),action需要是一個js對象
  • redux-thunk可以讓dispatch(action函數),action可以是一個函數
  • 該函數會被調用,并會傳給這個函數一個dispatch函數和getState函數
  • dispatch函數用于我們之后再次派發action
  • getState 函數考慮我們之后的一些操作需要依賴原來的狀態,用于讓我們可以獲取之前的一些狀態

如何使用redux-thunk

  1. 安裝redux-thunk
    yarn add redux-thunk
  2. 創建store時傳入應用了middleware的enhance函數
  • 通過applyMiddleware來結合多個Middleware,返回一個enhancer;
  • 將enhancer作為第二個參數傳入到createStore中;
// 通過applyMiddleware來結合多個Middleware, 返回一個enhancer
const enhancer = applyMiddleware(thunkMiddleware);
// 將enhancer作為第二個參數傳入到createStore中
const store = createStore(reducer, enhancer);
  1. 定義返回一個函數的action:
  • 注意:這里返回一個函數
  • 該函數在dispatch之后會被執行
const getHomeMultidataAction = () => {return (dispatch) => {axios.get("http://123.207.32.32:8000/home/multidata").then(res => {const data = res.data.data;dispatch(changeBannersAction(data.banner.list));dispatch(changeRecommendsAction(data.recommend.list));})}
}

combineReducers函數

  • 事實上,redux給我們提供了一個combineReducers函數可以讓我們方便對多個reducer進行合并
  • 那么combineReducers是如何實現的?
    • 它也是將我們傳入的reducers合并到一個對象中,最終返回一個combination函數(相當于我們之前的reducer函數)
    • 在執行combination函數的過程中,它會通過判斷前后返回的數據是否相同來決定返回之前的state還是新的state。
    • 新的state會觸發訂閱者發生對應的刷新,而舊的state可以有效的組織訂閱者發生刷新。

Redux 基本原理

所有的狀態都以對象樹的方式(state)存放于單個store中。
唯一改變狀態樹(state tree)的方法是創建action:一個描述發生了什么的對象,并將其dispatch派發給store。要指定狀態樹如何響應action來進行更新,你可以編寫純reducer函數,這些函數根據舊的state和action來計算新state。
新的state被創建后,對象會自動傳遞給所有注冊了監聽器的組件,從而觸發組件的重新渲染,使得界面始終保持與當前的state對象一致。
在這里插入圖片描述
在這里插入圖片描述

Redux在React中具體的使用方法

官方建議,安裝其他兩個插件 Redux Toolkit和React-Redux

  1. React Toolkit(RTK):官方推薦編寫Redux邏輯的方式,是一套工具的集合,簡化書寫方式
  2. React-Redux:用來鏈接 Redux和React組件的中間件
    在這里插入圖片描述
  3. 安裝方式
    npm install @reduxjs/toolkit react-redux

Redux Toolkit(RTK)

1. createSlice 函數

作用:創建一個Redux的slice。它接受一個包含reducer函數,slice名稱和初始狀態的配置對象,并返回一個包含reducer和action creators的對象。
參數

  • name:slice的名稱,用于標識狀態的一部分。
  • initialState:slice的初始狀態,定義了狀態的初始值‘
  • reducers:一個對象,包含一組同步的reducer函數,用于更新狀態。
    返回值:
    createSlice 返回一個包含以下屬性的對象:
  • name:slice的名稱
  • reducer:一個reducer 函數,用于處理來自action creators的動作并更新狀態
  • actions:一組action creators,用于創建派發給reducer的動作。

栗子 🌰:

import { createSlice } from '@reduxjs/toolkit';// 定義初始狀態
const initialState = {count: 0,
};// 創建一個 Redux slice
const counterSlice = createSlice({name: 'counter',initialState,reducers: {// 定義同步的 reducer 函數increment(state) {state.count += 1;},decrement(state) {state.count -= 1;},// 可以接受額外參數的 reducer 函數incrementByAmount(state, action) {state.count += action.payload;},},
});// 導出action creators
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// 導出reducer
export default counterSlice.reducer;

上述代碼使用 createSlice 函數創建一個名為 counter 的slice。包含一個名為 count的狀態和三個同步的reducer函數:increment,derement和incrementByAmount。

  • 通過increment,decrement,incrementByAmount 派發動作
    通過counterSlice.reducer 處理動作

configureStore 函數

作用:創建一個Redux store,它接受一個包含reducer函數和其他配置選項的對象,并返回一個Redux store 實例。
參數

  • reducer:一個或多個reducer函數,用于處理來自action creators 的動作并更新狀態
  • 其他配置選項:包括 middleware,devTools 等,用于配置store的行為。
    返回值
  • configureStore 返回一個Redux store 實例,它包含以下屬性和方法:
    • getState():用于獲取當前的狀態
    • dispatch(action):用于派發一個動作,以觸發狀態的更新
    • subscribe(listener):用于添加一個狀態變化的監聽器,當狀態發生變化時會被調用
    • replaceReducer(nextReducer):用于替換當前的reducer

栗子🌰:

import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers'; // 導入根 reducer// 創建 Redux store
const store = configureStore({reducer: rootReducer,// middleware: getDefaultMiddleware => getDefaultMiddleware(), // 使用默認的中間件// devTools: process.env.NODE_ENV !== 'production', // 在開發環境啟用 Redux DevTools
});export default store

在栗子中,我們使用configureStore 函數創建了一個Redux store
我們傳入了一個根reducer rootReducer,它是一個包含所有reducer的對象。我們還配置了默認的中間件,并在開發環境下啟用了Redux DevTools。

react-redux

它將所有組件分為兩大類:UI 組件和容器組件。

  1. UI 組件:負責呈現頁面(React)
  2. 容器組件:負責管理數據和業務邏輯(Redux)

react-redux中常用的組件及方法

Provider 組件

作用:將Redux的store 傳遞給整個React應用程序,使得所有組件都能夠訪問到redux的狀態。通過provider,我們可以在任何地方使用redux的狀態和派發動作。

好處:在整個應用程序中,任何一個組件都可以通過connect函數或useSelector鉤子函數來訪問Redux store 中的狀態,而不需要手動將store傳遞給每一個組件。

  • 簡化代碼:不需要在每一個組件中手動傳遞store,通過Provider,store可以在整個應用程序中自動傳遞給需要的組件。
  • 避免prop drilling:避免了在組件層級結構中進行多層次的prop 傳遞,提高了代碼的可維護性和可讀性。
  • 一致性:所有的組件都使用相同的redux store,保證了應用程序狀態的一致性。
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";import store from './store';
import { Provider } from 'react-redux';const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Provider store={store}><App /></Provider>
)

參考

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/38176.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38176.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38176.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

武漢星起航:無錫跨境電商加速“出海”,物流升級助品牌全球布局

隨著全球化的不斷深入&#xff0c;跨境電商作為數字外貿的新業態&#xff0c;正逐漸成為無錫企業拓展海外市場的重要渠道。武漢星起航關注到&#xff0c;近年來&#xff0c;無錫市通過積極推進國際物流樞紐建設&#xff0c;完善海外倉布局&#xff0c;以及各特色產業帶的積極參…

2024 年江西省研究生數學建模競賽題目 A題交通信號燈管理--完整思路、代碼結果分享(僅供學習)

交通信號燈是指揮車輛通行的重要標志&#xff0c;由紅燈、綠燈、 黃燈組成。紅燈停、綠燈行&#xff0c;而黃燈則起到警示作用。交通 信號燈分為機動車信號燈、非機動車信號燈、人行橫道信號 燈、方向指示燈等。 一般情況下&#xff0c;十字路口有東西向和南北向 4 個方向的車…

SpringSecurity中文文檔(Servlet Session Management)

Authentication Persistence and Session Management 一旦您擁有了正在對請求進行身份驗證的應用程序&#xff0c;就必須考慮如何在將來的請求中持久化和恢復結果身份驗證。 默認情況下&#xff0c;這是自動完成的&#xff0c;因此不需要額外的代碼&#xff0c;盡管了解 requ…

手機歌曲怎么轉換成mp3格式,手機電腦都能輕松搞定

不同的手機和音樂應用可能支持不同的音頻格式&#xff0c;而MP3作為一種廣泛兼容的音頻格式&#xff0c;因其體積小、音質相對較好的特點&#xff0c;至今仍被廣泛使用。 如果您想將手機中的歌曲轉換成MP3格式&#xff0c;以便于在更多設備上播放或節省存儲空間&#xff0c;本…

iOS端授權頁添加自定義按鈕

如何添加自定義控件 基于一鍵登錄的拉起授權頁面功能&#xff0c;如果想要在我們的授權頁面中添加自定義組件&#xff0c;例如使用其他方式登錄的按鈕&#xff0c;來實現其他方式登錄功能&#xff0c;為用戶呈現更多選擇登錄的方式。本文介紹如何在一鍵登錄授權界面中實現添加…

機器學習之監督學習

整理一下機器學習中監督學習相關內容&#xff0c;爭取梳理出一條易于理解和掌握的脈絡。下面會有很多相關參考博客和文章&#xff0c;先放到一起&#xff0c;最后再做個整體的梳理。持續更新中。。。。。。 監督學習作為機器學習的核心分支&#xff0c;其理論體系與實踐應用都…

C# 警告 warning MSB3884: 無法找到規則集文件“MinimumRecommendedRules.ruleset”

警告 warning MSB3884: 無法找到規則集文件“MinimumRecommendedRules.ruleset” C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\Microsoft.CSharp.CurrentVersion.targets(129,9): warning MSB3884: 無法找到規則集文件“MinimumRe…

競賽選題 python的搜索引擎系統設計與實現

0 前言 &#x1f525; 優質競賽項目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系統設計與實現 &#x1f947;學長這里給一個題目綜合評分(每項滿分5分) 難度系數&#xff1a;3分工作量&#xff1a;5分創新點&#xff1a;3分 該項目較為新穎&#xff…

正則表達式在Java中的應用與實例

正則表達式在Java中的應用與實例 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 正則表達式是一種強大的工具&#xff0c;用于模式匹配和字符串處理。在Java中…

武漢星起航:成功掛牌上股交,引領跨境電商行業進入全新發展階段

2023年10月30日&#xff0c;武漢星起航電子商務有限公司在上海股權托管交易中心成功掛牌展示&#xff0c;這一里程碑式的事件標志著武漢星起航正式登陸資本市場&#xff0c;開啟了公司發展的新篇章。作為亞馬遜跨境電商領域的領軍企業之一&#xff0c;武漢星起航此次掛牌不僅是…

文件操作詳解(C語言)

1.為什么要用到文件&#xff1f;怎樣數據才能持久化&#xff1f; 保存在內存中的數不安全&#xff08;一次斷電&#xff0c;忘記保存&#xff0c;不用了還給系統&#xff09; 持久化&#xff1a;保存在硬盤上&#xff08;放在文件中&#xff09; 什么是文件&#xff1f;文件…

Hadoop-08-HDFS集群 基礎知識 命令行上機實操 hadoop fs 分布式文件系統 讀寫原理 讀流程與寫流程 基本語法上傳下載拷貝移動文件

章節內容 上一節完成&#xff1a; HDFS的簡介內容HDFS基礎原理HDFS讀文件流程HDFS寫文件流程 背景介紹 這里是三臺公網云服務器&#xff0c;每臺 2C4G&#xff0c;搭建一個Hadoop的學習環境&#xff0c;供我學習。 之前已經在 VM 虛擬機上搭建過一次&#xff0c;但是沒留下…

SpringSecurity的執行原理

SpringSecurity的執行原理&#xff1a;當我們服務端接收到請求后&#xff0c;首先通過DelegatingFilterProxy代理對象交互&#xff0c;轉發給springsecurity的執行鏈&#xff0c;由于他自帶的執行鏈有16條&#xff0c;我們將不用的過濾器進行了排除&#xff0c;同時加入了我們自…

如何保護應用?可快速部署的WAF服務器分享

Web應用攻擊是安全事件和數據泄露的主要原因。相關統計表明&#xff0c;超過四分之三的網絡犯罪直指應用及其漏洞。為保護數量日益增長的應用安全&#xff0c;Web應用防火墻(WAF)因此而生。本文則聚焦于WAF服務器&#xff0c;了解它的性能與具體的實踐應用。   新加坡網絡安全…

《單片機》期末考試復習-學習筆記總結

題型 問答題(15分)編程題(65分)編程題1(20分)編程題2(45分)設計題(20分)一、問答題 1.1.單片機概念和特點 1.2. 51單片機的中斷結構 1.3.主從式多機通訊的概念及其工作原理 多機通信是指兩臺以上計算機之間的數據傳輸,主從式多機通信是多機通信系統中最簡單的一種,…

PHP電商系統開發指南最佳實踐

電子商務系統開發的最佳實踐包括&#xff1a;數據庫設計&#xff1a;選擇適合關系型數據庫&#xff0c;優化數據結構&#xff0c;考慮表分區&#xff1b;安全&#xff1a;加密數據&#xff0c;防止 sql 注入&#xff0c;處理會話管理&#xff1b;用戶界面&#xff1a;遵循 ux 原…

vue3長列表優化,使用vue-virtual-scroller實現直播間彈幕列表虛擬滾動效果

使用的組件庫是&#xff1a;https://github.com/Akryum/vue-virtual-scroller 官方文檔&#xff1a;vue-virtual-scroller 安裝依賴 npm install --save vue-virtual-scrollernextpnpm install --save vue-virtual-scrollernextyarn add vue-virtual-scrollernext 組件導入…

如何用文章改寫ai軟件進行改寫?5個軟件教你快速進行修改文章

如何用文章改寫ai軟件進行改寫&#xff1f;5個軟件教你快速進行修改文章 使用AI改寫軟件可以幫助你快速重寫文章&#xff0c;使其更加流暢、符合要求或避免重復。以下是五款優質的AI改寫軟件&#xff0c;它們能夠幫助你快速進行文章修改&#xff1a; 聰明靈犀 這是一款非常簡…

數據結構_1.0

一、數據結構概述 1.1 概念 在計算機科學中&#xff0c;數據結構是一種數據組織、管理和存儲的格式 。它是相互之間存在一種或多種特定關系的數據元素的集合。通常情況下&#xff0c;精心選擇的數據結構可以帶來更高的運行或者存儲效率。數據結構往往同高效的檢索算法和索引技…

【開源合規】開源許可證基礎知識與風險場景引入

文章目錄 什么是開源許可證(License)?開源許可證有什么用?開源許可證分類開源許可證分類及描述公共代碼 (Public Domain)CC0無License寬松型許可證 (Permissive)MITApache 2.0BSD弱互惠型許可證 (Weak Copyleft)LGPLMPLEPL互惠型許可證 (Reciprocal)GPLEUPL強互惠許可證 (Str…