React(七):Redux

Redux基本使用

純函數:1.函數內部不能依賴函數外部變量;2.不能產生副作用,在函數內部改變函數外部的變量

React只幫我們解決了DOM的渲染過程,State還是要由我們自己來管理——redux可幫助我們進行管理

Redux三大特點

1.單一數據源:整個應用的狀態存儲在一個單一的對象樹,且該對象樹只存儲在一個store中

2.State是只讀的:狀態是不可直接修改的,必須通過觸發一個“action”來發起狀態的變更

3.使用純函數來完成狀態變更:通過reducer舊stateactions聯系在一起,并返回一個新的state;不產生任何副作用。

Redux測試項目搭建

step1:項目初始化

npm init

step2:安裝redux

npm i redux

step3:創建store倉庫,并存儲數據

const { createStore } = require('redux');
const {reducer} = require('./reducer');// 創建的store
const store = createStore(reducer);module.exports = store;

step4:創建reducer函數

const { ADD_NUMBER, CHANGE_NAME } = require("./constants")// 初始化的數據
const initialState = {name: "why",counter: 100
}function reducer(state = initialState, action) {switch(action.type) {case CHANGE_NAME:return { ...state, name: action.name }case ADD_NUMBER:return { ...state, counter: state.counter + action.num }default:return state}
}module.exports = reducer

注意:在該代碼中,我們將action的類型封裝到了constants.js文件中,方便復用

const ADD_NUMBER = "add_number"
const CHANGE_NAME = "change_name"module.exports = {ADD_NUMBER,CHANGE_NAME
}

step5:通過action來修改state

將它封裝到一個單獨的文件中

const { ADD_NUMBER, CHANGE_NAME } = require("./constants")const changeNameAction = (name) => ({type: CHANGE_NAME,name
})const addNumberAction = (num) => ({type: ADD_NUMBER,num
})module.exports = {changeNameAction,addNumberAction
}

然后在使用的組件中進行調用

const store = require("./store")
const { addNumberAction, changeNameAction } = require("./store/actionCreators")const unsubscribe = store.subscribe(() => {console.log("訂閱數據的變化:", store.getState())
})// 修改store中的數據: 必須action
store.dispatch(changeNameAction("kobe"))
store.dispatch(changeNameAction("lilei"))
store.dispatch(changeNameAction("james"))unsubscribe()// 修改counter
store.dispatch(addNumberAction(10))
store.dispatch(addNumberAction(20))
store.dispatch(addNumberAction(30))

最終,通過拆分代碼我們會形成4個文件:

  1. store/index.js文件
  2. store/reducer.js文件
  3. store/actionCreators.js文件
  4. store/constants.js文件

React中使用Redux

redux使用過程:首先會在一個中心的store里面存儲我們對應的狀態,然后就可以讓一些組件中store中訂閱一些數據;然后也可以在組件中通過dispatch來派發一些action,這些action就會到達Reducer里面,它就會自動執行該函數,并返回一個新的state對象,再根據新的state來更新數據。數據更新后就會自動告訴訂閱者,我現在數據發生改變了,需要拿新數據,界面再重新渲染

step1:創建一個項目并安裝redux

step2:創建store

step3:在組件中使用

import React, {PureComponent } from 'react'
import Home from './pages/Home'
import Profile from './pages/profile'
import "./style.css"
import store from './store'export class App extends PureComponent {constructor() {super()this.state = {count: store.getState().count}}componentDidMount() {// 訂閱storestore.subscribe(() => {const state = store.getState()this.setState({count: state.count})})}render() {const {count} = this.statereturn (<div><h2>App Count: {count}</h2><div className="pages"><Home /><Profile /></div></div>)}
}export default App

React-Redux

redux官方幫助我們提供了 react-redux 庫,可簡化在react中使用redux的過程

npm i react-reduxyarn add react-redux

Provider

在src/index.js中導入Provider,并包裹根組件→將Redux的store傳遞給整個應用程序→使得所有組件可訪問Redux的狀態

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>
);

connect

connect是React-redux提供的一個高階組件(HOC),用于將React組件與Redux的倉庫聯系起來;

它不會修改原始組件,而是返回一個新的、連接了Redux的組件

作用:

將Redux的狀態(state) 和(dispatch)映射到組件的props

通過 mapStateToPropsmapDispatchToProps,可以自定義組件需要的狀態和操作

import axios from "axios"
import * as actionTypes from  "./constants"export const calcNumber = (num) => {return {type:actionTypes.CALC_NUMBER,num}
}
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { calcNumber } from '../store/actionCreators'export class About extends PureComponent {calcNumber(num) {this.props.calcNumber(num)}render() {const {count,banners, recommends} = this.propsreturn (<div><h2>About:{count}</h2><button onClick={e => this.props.calcNumber(6)}>+6</button><button onClick={e => this.props.calcNumber(-6)}>-6</button><button onClick={e => this.props.calcNumber(10)}>+10</button><button onClick={e => this.props.calcNumber(-5)}>-5</button><div className="banners"><h2>輪播圖數據:</h2><ul>{banners.map(item => {return <li key={item.acm}>{item.title}</li>})}</ul></div><div className="recommend"><h2>推薦數據</h2><ul>{recommends.map(item => {return <li key={item.acm}>{item.title}</li>})}</ul></div></div>)}
}function mapStateToProps(state){return {count: state.count,banners:state.banners,recommends:state.recommends}
}const mapDispatchToProps = (dispatch) => {return {calcNumber(num) {dispatch(calcNumber(num))}}
}// connect()返回值是一個高階組件
export default connect(mapStateToProps,mapDispatchToProps)(About)

組件中進行異步操作

網絡請求可以在class組件的componentDidMount中發送

store/home.js?

import axios from "axios"
import * as actionTypes from  "./constants"export const changeBanners = (banners) => {return {type:actionTypes.CHANGE_BANNERS,banners}
}export const changeRecommends = (recommends) => {return {type:actionTypes.CHANGE_RECOMMENDS,recommends}
}

Home.jsx?

import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import axios from 'axios'
import { changeBanners, changeRecommends } from '../store/actionCreators'export class Category extends PureComponent {componentDidMount() {axios.get("http://123.207.32.32:8000/home/multidata").then(res => {const banners = res.data.data.banner.listconst recommends = res.data.data.recommend.listthis.props.changeBanners(banners)this.props.changeRecommends(recommends)})}render() {return (<div><h2>Category Page:</h2></div>)}
}const mapDispatchToProps = (dispatch) => {return {changeBanners(banners) {dispatch(changeBanners(banners))},changeRecommends(recommends) {dispatch(changeRecommends(recommends))}}
}export default connect(null,mapDispatchToProps)(Category)

redux中進行異步操作

網絡請求的數據也屬于狀態管理的一部分,我們最好還是將它放在redux中來管理

在默認情況下,dispatch(action)中傳入的是一個對象→可通過reduc-thunk讓dispatch中傳入一個action函數

step1:安裝redux-thunk

npm i redux-thunk

step2:在創建store時傳入應用了middleware的enhance函數

  • 通過applyMiddleware來結合多個Middleware, 返回一個enhancer;
  • 將enhancer作為第二個參數傳入到createStore中;
import { createStore,applyMiddleware } from "redux";
import {thunk} from "redux-thunk"
import reducer from "./reducer";// 正常情況下,store.dispatch(object) 只能派發一個對象
// 想要派發函數store.dispatch(function) 需要做一個增強
const store = createStore(reducer,applyMiddleware(thunk))export default store

step3:定義返回一個函數的action

import axios from "axios"
import * as actionTypes from  "./constants"export const changeBanners = (banners) => {return {type:actionTypes.CHANGE_BANNERS,banners}
}export const changeRecommends = (recommends) => {return {type:actionTypes.CHANGE_RECOMMENDS,recommends}
}export const fetchHomeMultidataAction = () => {// 如果是一個普通的action,那么我們需要返回一個對象// 問題:對象中不能直接拿到從服務器請求的數據// return {}return function(dispatch,getState) {// 異步操作:網絡請求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(changeBanners(banners))dispatch(changeRecommends(recommends))})}
}

step4:在組件中進行派發

import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { fetchHomeMultidataAction } from '../store/actionCreators'export class Category extends PureComponent {componentDidMount() {this.props.fetchHomeMultidata()}render() {return (<div><h2>Category Page:</h2></div>)}
}const mapDispatchToProps = (dispatch) => {return {fetchHomeMultidata() {dispatch(fetchHomeMultidataAction())}}
}export default connect(null,mapDispatchToProps)(Category)

Redux模塊拆分

在開發中,如果將所有的數據都存儲在一個state中,隨著數據越來越多,會難以管理與維護;

我們可以對其進行模塊的拆分

combineReducers底層原理

redux給我們提供了一個combineReducers函數可以方便的讓我們對多個reducer進行合并

實現原理:

  • 將我們傳入的reducers合并到一個對象中,最終返回一個combination函數
  • 在執行combination函數的過程中,會通過判斷前后返回的數據是否相同來決定返回之前的state還是新的state
  • 新的state會觸發訂閱者發生對應的刷新,而舊的state可以有效的組織訂閱者發生刷新
// 實現原理
function reducer(state={},action) {// 返回一個對象,作為store的狀態return {count:counterReducer(state.count,action),home:homeReducer(state.home,action),user:userReducer(state.user,action)}
}

Redux Toolkit(RTK)

簡介

它封裝了Redux的核心API,并提供了一些額外工具和約定,幫助我們更高效編寫Redux代碼

安裝:

npm install @reduxjs/toolkit react-redux

核心API:

  • configureStore:它自動配置了 Redux 的 createStoreapplyMiddleware,并預裝了一些常用的中間件(如 redux-thunkredux-devtools-extension
  • createSlice:接受reducer函數的對象、切片名稱和初始狀態值,并自動生成切片reducer,并帶有相應的actions
  • createAsyncThunk:接受一個動作類型字符串和一個返回承諾的函數,并生成一個pending/fulfilled/rejected基于該承諾分派動作類型的 thunk

基本使用

1.configureStore創建大倉庫store

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counter";const store = configureStore({reducer: {count: counterReducer,},
});export default store;

2.createSlice創建小倉庫

import { createSlice } from "@reduxjs/toolkit";const counterSlice = createSlice({name: "counter",initialState: {count: 100},reducers: {increment: (state, action) => {state.count += action.payload;},decrement: (state, action) => {state.count -= action.payload;}}   
})export const{increment, decrement} = counterSlice.actions
export default counterSlice.reducer;

3.將模塊的reducer導入大倉庫中

4.在組件中使用數據——還是和之前一樣(Provider、connect)

異步使用

1.使用 createAsyncThunk 創建異步操作

2.?在?createSlice?中處理異步操作的結果

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";export const fetchHomeMultidataAction = createAsyncThunk("home/multidata", async () => {const res = await axios.get("http://123.207.32.32:8000/home/multidata");// 返回結構,那么action狀態就會變成fulfilled狀態return res.data;
});const homeSlice = createSlice({name: "home",initialState: {banners: [],recommends: []},reducers: {changeBanners(state, { payload }) {state.banners = payload;},changeRecommends(state, { payload }) {state.recommends = payload;}},extraReducers: (builder) => {builder.addCase(fetchHomeMultidataAction.pending, (state, action) => {console.log("fetchHomeMultidataAction pending");}).addCase(fetchHomeMultidataAction.fulfilled, (state, action) => {console.log("fetchHomeMultidataAction fulfilled");// 這里的數據不需要淺拷貝——因為內部的ImmutableJS重構了redux,并返回了一個新對象state.banners = action.payload.data.banner.list;state.recommends = action.payload.data.recommend.list;}).addCase(fetchHomeMultidataAction.rejected, (state, action) => {console.log("fetchHomeMultidataAction rejected");});}
});export const { changeBanners, changeRecommends } = homeSlice.actions;
export default homeSlice.reducer;

3.在組件中調用該函數即可——與原來使用一樣

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

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

相關文章

《Android低內存設備性能優化實戰:深度解析Dalvik虛擬機參數調優》

1. 痛點分析&#xff1a;低內存設備的性能困局 現象描述&#xff1a;大應用運行時頻繁GC導致卡頓 根本原因&#xff1a;Dalvik默認內存參數與硬件資源不匹配 解決方向&#xff1a;動態調整堆內存參數以平衡性能與資源消耗 2. 核心調優參數全景解析 關鍵參數矩陣&#xff1…

STC89C52單片機學習——第38節: [17-2] 紅外遙控紅外遙控電機

寫這個文章是用來學習的,記錄一下我的學習過程。希望我能一直堅持下去,我只是一個小白,只是想好好學習,我知道這會很難&#xff0c;但我還是想去做&#xff01; 本文寫于&#xff1a;2025.03.30 51單片機學習——第38節: [17-2] 紅外遙控&紅外遙控電機 前言開發板說明引用…

計算機組成原理————計算機運算方法精講<1>原碼表示法

第一部分:無符號數和有符號數的概念 1.無符號數 計算機中的數均存放在寄存器當中,通常稱寄存器的位數為機器字長,所謂無符號數,就是指沒有fu5號的數,在寄存器中的每一位均可用來存放數值,當存放有符號數時,需要留出位置存放符號,機器字長相同時,無符號數與有符號數所…

【什么是機器學習——多項式逼近】

什么是機器學習——多項式逼近 機器學習可以分成三大類別,監督學習、非監督學習、強化學習。三大類別背后的數學原理不同。監督學習使用了數學分析中的函數逼近方法和概率統計中的極大似然方法;非監督學習使用聚類和EM算法;強化學習使用馬爾可夫決策過程的想法。 機器學習的…

Ubuntu 22.04 上安裝阿里云 CLI(命令行工具)

在 Ubuntu 22.04 上安裝阿里云 CLI&#xff08;命令行工具&#xff09;可以通過以下步驟完成&#xff1a; 步驟 1&#xff1a;下載阿里云 CLI 安裝包 打開終端&#xff0c;首先更新你的軟件包索引&#xff1a; sudo apt update安裝 curl&#xff08;如果還沒有安裝&#xff09…

?Android Gradle 插件(AGP)版本與 ?Gradle 版本需要嚴格對應

一、AGP 與 Gradle 版本對照表 Android Gradle 插件版本對應 Gradle 版本適用 Android Studio 版本?8.1.x8.2Arctic Fox (2020.3.1+)?8.0.x8.0Arctic Fox (2020.3.1+)?7.4.x7.5.1IntelliJ IDEA 2022+?7.3.x7.4IntelliJ IDEA 2022+?7.2.x7.3.3IntelliJ IDEA 2021.3+?7.1.x…

【Matlab】-- 基于MATLAB的灰狼算法優化支持向量機的回歸算法

文章目錄 文章目錄 01 內容概要02 GWO-SVR模型03 部分代碼04 運行結果05 參考文獻06 代碼下載 01 內容概要 GWOSVR&#xff08;基于灰狼算法優化的支持向量機回歸&#xff09;是一種先進的機器學習技術&#xff0c;它結合了灰狼優化算法&#xff08;Grey Wolf Optimizer, GWO…

Google Play Games PC版即將正式上線!

早在 2021 年&#xff0c;谷歌就推出 Google Play Games PC 版&#xff0c;本質上是基于虛擬化創建安卓系統在 Windows 上運行 Google Play 平臺的各種游戲。 在測試了 4 年后&#xff0c;谷歌準備在今年晚些時候正式上線該平臺&#xff0c;谷歌將在下周舉辦 2025 游戲開發者大…

【SpringBoot】深入解析使用配置文件解決硬編碼問題綜合練習(三):解析驗證碼拓展問題

校驗輸入驗證碼接口 check( ) 5. 為什么要用靜態內部類接收配置文件中的 Seisson 對象&#xff1f; 為什么我們接收配置文件的 Session 對象時&#xff0c;使用靜態內部類給 Session 對象的 key&#xff0c;date 屬性賦值呢&#xff1f;不加 static 可以嗎&#xff1f; 在 Cap…

day16 學習筆記

文章目錄 前言一、廣播機制二、數組遍歷1.for循環2.nditer函數 三、數組操作1.reshape函數2.flat屬性3.flatten函數4.revel函數5.數組轉置6.升維與降維7.數組的連接與分割8.數組運算 前言 通過今天的學習&#xff0c;我進一步掌握了更多numpy的語法知識 一、廣播機制 廣播&am…

使用FastExcel時的單個和批量插入的問題

在我們用excel表進行插入導出的時候&#xff0c;通常使用easyexcel或者FastExcel&#xff0c;而fastexcel是easy的升級版本&#xff0c;今天我們就對使用FastExcel時往數據庫插入數據的業務場景做出一個詳細的剖析 場景1 現在我們數據庫有一張組織表&#xff0c;組織表的字段…

Cannot find a valid baseurl for repo: centos-sclo-sclo/x86_64

? rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-latest-5.0.el7.noarch.rpmyum clean allyum macache fast? 編輯配置文件 /etc/yum.repos.d/zabbix.repo and enable zabbix-frontend repository. [zabbix-frontend]...enabled1... 下載相關…

AI基礎02-圖片數據采集

上篇文章我們學習了文本的數據采集&#xff0c;今天主要了解一下圖片數據采集的方法。圖片采集方法通常有網頁采集和實時采集&#xff08;傳感器采集&#xff09;兩種。我們學習一下如何利用python 工具和筆記本計算機攝像頭進行圖片數據的實時采集。 1&#xff09;cv2庫簡介 …

【CSS】相對位置小練習

要求&#xff1a; 成果&#xff1a; 代碼&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>相對位置小練習</title><link rel"stylesheet" href"./css/style.css…

外設的中斷控制

如ADC、SPI、I2C、TIM等使用STM32 HAL庫時的中斷函數調用方式和UART非常類似&#xff0c;都有底層直接使能中斷和上層庫函數管理兩種方式。下面詳細說明幾種典型外設&#xff1a; 一、ADC外設 &#xff08;1&#xff09;直接使能中斷&#xff08;底層控制&#xff09;&#xf…

網絡傳輸優化之多路復用與解復用

一、基本概念 多路復用 發送端將來自多個應用或進程的數據流合并到同一物理信道中傳輸的過程。核心目的是提高信道利用率&#xff0c;減少資源浪費。例如&#xff0c;多個網絡應用&#xff08;如瀏覽器、郵件客戶端&#xff09;通過不同端口將數據封裝為報文段&#xff0c;共享…

【軟考-架構】10.1、軟件工程概述-CMM-軟件過程模型-逆向工程

?資料&文章更新? GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目錄 軟件工程基礎知識軟件工程概述能力成熟度模型能力成熟度模型CMM能力成熟度模型集成CMMI &#x1f4af;考試真題第一題第二題 軟件過程模型瀑布模型&#xff08;SDLC&#…

python將整個txt文件寫入excel的一個單元格?

要將整個txt文件寫入Excel的一個單元格&#xff0c;可以使用Python的openpyxl庫來實現。以下是一個簡單的示例代碼&#xff1a; from openpyxl import Workbook# 讀取txt文件內容 with open(file.txt, r) as file:txt_content file.read()# 創建一個新的Excel工作簿 wb Work…

車載以太網網絡測試 -25【SOME/IP-報文格式-1】

1 摘要 本專題接著上一專題對SOME/IP進行介紹&#xff0c;主要對SOME/IP報文格式以及定義的字段進行詳細介紹&#xff0c;有助于在實際項目過程中對SOME/IP報文的理解。 上文回顧&#xff1a; 車載以太網網絡測試 -24【SOME/IP概述】 2 SOME/IP-報文格式 通過上個專題介紹&a…

【區塊鏈安全 | 第五篇】DeFi概念詳解

文章目錄 DeFi1. DeFi 生態概覽2. 去中心化交易所&#xff08;DEX&#xff09;2.1 AMM&#xff08;自動做市商&#xff09;模型2.2 訂單簿模式&#xff08;現貨交易&#xff09; 3. 借貸協議3.1 Aave3.2 使用閃電貸&#xff08;Flash Loan&#xff09; 4. 穩定幣&#xff08;St…