React狀態管理Context API + useReducer

在 React 中,Context API + useReducer 是一種輕量級的狀態管理方案,適合中小型應用或需要跨組件共享復雜狀態的場景。它避免了 Redux 的繁瑣配置,同時提供了清晰的狀態更新邏輯。


1. 基本使用步驟

(1) 定義 Reducer

類似于 Redux 的 reducer,用于處理狀態更新邏輯:

// reducer.js
export const initialState = {count: 0,user: null,
};export function reducer(state, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };case 'DECREMENT':return { ...state, count: state.count - 1 };case 'SET_USER':return { ...state, user: action.payload };default:return state;}
}

(2) 創建 Context 和 Provider

使用 createContext 創建 Context,并用 useReducer 管理狀態:

// AppContext.js
import { createContext, useReducer } from 'react';
import { initialState, reducer } from './reducer';// 1. 創建 Context
export const AppContext = createContext();// 2. 創建 Provider 組件
export function AppProvider({ children }) {const [state, dispatch] = useReducer(reducer, initialState);return (<AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>);
}

(3) 在頂層組件包裹 Provider

// App.js
import { AppProvider } from './AppContext';
import Counter from './Counter';function App() {return (<AppProvider><Counter /></AppProvider>);
}

(4) 在子組件使用狀態

通過 useContext 獲取 statedispatch

// Counter.js
import { useContext } from 'react';
import { AppContext } from './AppContext';export function Counter() {const { state, dispatch } = useContext(AppContext);return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button><button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button></div>);
}

2. 數據持久化

Context + useReducer 管理的狀態是純內存狀態,當頁面刷新時,這些數據會丟失,因為 JavaScript 的內存會被清空,恢復到初始狀態。
在 React 的 Context + useReducer 架構中實現數據持久化( localStorage sessionStorage,頁面刷新不丟失)

2.1實現步驟

(1)定義 Reducer(持久化/非持久化/臨時數據)
// reducer.js
export const initialState = {// 需要持久化的數據persistedData: { language: 'en' },// 非持久化數據sessionData: { loginForm: null },// 臨時數據tempData: {count: 0}
};export function reducer(state, action) {switch (action.type) {// 持久化數據case 'SET_LANGUAGE':return { ...state, persistedData: { ...state.persistedData, language: action.payload } };// 非持久化數據case 'SET_LOGIN_FORM':return { ...state, sessionData: { ...state.sessionData, loginForm: action.payload } };// 臨時數據case 'SET_COUNT':return {...state, tempData: { ...state.tempData, count: action.payload } }default:return state;}
}
(2)帶持久化的Provider組件實現
// AppContext.jsx
import { createContext, useReducer, useEffect } from 'react';
import { initialState, reducer } from './reducer';// 1. 創建 Context
export const AppContext = createContext();// 2. 創建 Provider 組件
export function AppProvider({ children }) {const [state, dispatch] = useReducer(reducer,{...initialState,persistedData: JSON.parse(localStorage.getItem('persistedData')) || initialState.persistedData,sessionData: JSON.parse(sessionStorage.getItem('sessionData')) || initialState.sessionData});// 監聽localStorage字段的變化useEffect(() => {localStorage.setItem('persistedData', JSON.stringify(state.persistedData));}, [state.persistedData]);// 監聽sessionStorage 字段的變化useEffect(() => {sessionStorage.setItem('sessionData', JSON.stringify(state.sessionData));}, [state.sessionData]);return (<AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>);
}
(3)在頂層組件包裹 Provider
// app.jsx
import { RouterProvider } from "react-router";
import router from "./router/index.jsx";
import { AppProvider } from '@stores/AppContext.jsx';
function App() {return (<AppProvider><div className="app"><RouterProvider router={router} /></div></AppProvider>)
}export default App

2.2 純 localStorage 與 Context + useReducer + localStorage對比

1、 純 localStorage特點

優點缺點
1. 實現簡單,無需額外庫1. 狀態不同步:多個組件無法實時共享同一份數據
2. 適合極簡場景2. 重復代碼:每個組件需單獨處理存儲邏輯
3. 無性能開銷(僅讀寫存儲)3. 難以維護:業務復雜時邏輯分散

2、 Context + useReducer + localStorage特點

優點缺點
1. 狀態全局共享:所有組件實時響應變化1. 代碼量稍多(需設置 Context/Reducer)
2. 邏輯集中:易于維護和擴展2. 小型項目可能過度設計
3. 自動持久化:狀態變更自動同步到存儲3. 需處理 Provider 嵌套問題

核心區別對比

對比維度純 localStorageContext + useReducer + localStorage
狀態同步需手動觸發,組件間不同步自動同步,全局狀態一致
代碼組織邏輯分散在各組件集中管理,高內聚低耦合
維護性難擴展,易出現重復代碼易于擴展和維護
性能直接操作存儲,無額外開銷有 Context 的渲染開銷(可通過 memo 優化)
適用場景簡單頁面、獨立組件中大型應用、需共享狀態的場景

總結

  • 直接 localStorage:簡單粗暴,適合局部狀態。
  • Context + useReducer + localStorage:專業方案,適合全局狀態。

2.3注意事項

  • localStorage /sessionStorage只能存字符串,復雜數據需用 JSON.stringify
  • 優點:1、代碼簡潔,適合小型應用;2、無需第三方庫;
  • 缺點: 1、 localStorage/sessionStorage是同步操作,可能阻塞主線程;2、存儲大小有限(通常 5MB);

2. 進階優化

(1) 封裝自定義 Hook

避免在每個組件里重復寫 useContext

// hooks/useAppContext.js
import { useContext } from 'react';
import { AppContext } from '../AppContext';export function useAppContext() {return useContext(AppContext);
}

然后在組件中使用:

const { state, dispatch } = useAppContext();

(2) 優化性能(避免不必要的渲染)

默認情況下,Context 的更新會導致所有消費者組件重新渲染。可以使用 memo + 拆分 Context 優化:

// 拆分多個 Context
const CountContext = createContext();
const UserContext = createContext();// 在 Provider 里分別提供
<CountContext.Provider value={{ countState, countDispatch }}><UserContext.Provider value={{ userState, userDispatch }}>{children}</UserContext.Provider>
</CountContext.Provider>

(3) 結合異步操作

可以在 dispatch 里處理異步邏輯(如 API 請求):

async function fetchUser(dispatch) {try {const user = await fetch('/api/user').then(res => res.json());dispatch({ type: 'SET_USER', payload: user });} catch (error) {dispatch({ type: 'SET_ERROR', payload: error.message });}
}// 在組件中調用
fetchUser(dispatch);

3. 優缺點對比

優點缺點
無需額外庫,React 原生支持大型應用可能性能較差(需手動優化)
比 Redux 更輕量異步處理較麻煩(需手動封裝)
適合中小型應用調試不如 Redux 方便(無 DevTools)

4. 適用場景

  • 小型/中型應用:不想引入 Redux 或 Zustand 時。
  • 組件層級較深:需要跨多層傳遞狀態時。
  • 簡單全局狀態:如主題、用戶登錄信息等。

總結

  • Context + useReducer 是 React 內置的狀態管理方案,適合輕量級需求。
  • 對于更復雜的狀態管理,可考慮 ZustandRedux Toolkit
  • 如果涉及大量異步邏輯,建議結合 React QuerySWR 使用。

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

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

相關文章

3 個優質的終端 GitHub 開源工具

1、Oh My Zsh Oh My Zsh 是一個幫助你管理和美化 zsh 終端的開源工具。它讓你的終端更炫酷、更高效。安裝后&#xff0c;你可以快速使用各種插件和主題&#xff0c;比如常見的 git 命令簡化、支持多種編程語言工具等&#xff0c;每次打開終端都會有驚喜。無論你是開發者還是普…

無人機巡檢智能邊緣計算終端技術方案??——基于EFISH-SCB-RK3588工控機/SAIL-RK3588核心板的國產化替代方案?

一、方案核心價值? ?實時AI處理?&#xff1a;6TOPS NPU實現無人機影像的實時缺陷檢測&#xff08;延遲&#xff1c;50ms&#xff09;?全國產化?&#xff1a;芯片、操作系統、算法工具鏈100%自主可控?極端環境適配?&#xff1a;-40℃~85℃穩定運行&#xff0c;IP65防護等…

SpringAI 1.0.0 正式版——利用Redis存儲會話(ChatMemory)

官方文檔&#xff1a;Chat Memory :: Spring AI Reference 1. 引言 SpringAI 1.0.0 改動了很多地方&#xff0c;本文根據官方的InMemoryChatMemoryRepository實現了自定義的RedisChatMemoryRepository&#xff0c;并使用MessageWindowChatMemory創建ChatMemory 2. 實現 2.1.…

RFC8489-STUN

0. 學習參考 RFC5389 中文翻譯 中文RFC RFC文檔 RFC翻譯 RFC中文版 RFC 5389&#xff1a;NAT 的會話遍歷實用程序 &#xff08;STUN&#xff09; --- RFC 5389: Session Traversal Utilities for NAT (STUN) 1. RFC 3489的演變 自 RFC 3489 發布以來的經驗發現&#xff0c;…

開始在本地部署自己的 Gitea 服務器

0.簡介 在軟件開發和團隊協作中&#xff0c;代碼管理是至關重要的環節。筆者一直使用gitblit管理自己的倉庫。然鵝&#xff0c;這個軟件已經很久沒有更新了。經過多方考察&#xff0c;發現Gitea 是一款輕量級的開源代碼托管平臺&#xff0c;具有易于部署、資源占用少、功能豐富…

Xsens-AAA工作室品質,為動畫師準備

每一幀都講述著一個故事&#xff0c;當動作真實呈現時&#xff0c;故事便鮮活起來。我們打造并改進了 Xsens Animate&#xff0c;助力專業人士突破數字動畫的界限。 通過升級后的 Xsens Animate&#xff0c;您可以獲得女性和男性解剖模型以及更精確的運動引擎&#xff0c;從一…

嵌入(Embedding)技術的實現原理與應用場景解析

嵌入&#xff08;Embedding&#xff09;技術的實現原理與應用場景解析 引言&#xff1a;從One-Hot到語義空間 在自然語言處理的演進歷程中&#xff0c;嵌入技術&#xff08;Embedding&#xff09;的誕生標志著一個重要轉折點——它讓離散的符號表示突破了維度詛咒&#xff0c…

金倉數據庫征文-金倉KES數據同步優化實踐:邏輯解碼與增量同步

目錄 一.同步場景與方案選型 二.什么是KES 三.同步環境配置 1.前置條件驗證 2.邏輯解碼配置 四.同步實施與問題排查 1.結構映射規則 2.增量數據捕獲 3.數據一致性校驗 五.性能調優實踐 1.同步線程優化 2.批量提交優化 3.資源監控指標 六.典型場景解決方案 1.雙向…

開源語義分割工具箱mmsegmentation基于Lovedata數據集訓練模型

開源語義分割工具箱mmsegmentation安裝環境 文章目錄 1、下載數據集2、整理數據集3、下載預訓練模型4、測試5、訓練模型參考官方數據處理步驟 https://github.com/open-mmlab/mmsegmentation/blob/main/docs/zh_cn/user_guides/2_dataset_prepare.md#loveda 數據集類別標簽:…

Python概率統計可視化——概率分布、假設檢驗與分子運動模型

Python概率統計可視化——概率分布、假設檢驗與分子運動模型 前言 概率統計作為描述不確定性和隨機現象的數學工具&#xff0c;廣泛應用于物理學、生物學、經濟學等領域。然而&#xff0c;抽象的概率分布和統計推斷過程往往難以直觀理解。可視化技術通過將概率密度、假設檢驗邏…

NLP學習路線圖(二十二): 循環神經網絡(RNN)

在自然語言處理&#xff08;NLP&#xff09;的廣闊天地中&#xff0c;序列數據是絕對的核心——無論是流淌的文本、連續的語音還是跳躍的時間序列&#xff0c;都蘊含著前后緊密關聯的信息。傳統神經網絡如同面對一幅打散的拼圖&#xff0c;無法理解詞語間的順序關系&#xff0c…

禪道5月更新速覽 | 新增交付物配置功能,支持建立跨執行任務依賴關系,研發效能平臺上線

禪道體驗又升級啦&#xff01;禪道5月新功能合集來啦&#xff0c;研發效能平臺與大家見面啦&#xff01; 我們將繼續堅持&#xff0c;月月有大招&#xff0c;迭代不停歇&#xff0c;快來更新禪道&#xff0c;體驗全新的項目管理工具吧~ ?

【PDF PicKiller】PDF批量刪除固定位置圖片工具,默認解密,可去一般圖、背景圖、水印圖!

PDF批量刪除固定位置圖片工具 PDF PicKiller <center>PDF PicKiller [Download](https://github.com/Peaceful-World-X/PDF-PicKiller)&#x1f929; 工具介紹&#x1f973; 主要功能&#x1f92a; 軟件使用&#x1f92a; 參數解釋&#x1f92a; 關鍵代碼&#x1f929; 項…

kubeadm安裝k8s

1、環境準備 1.1、升級系統內核 參考另一篇文章&#xff1a;https://blog.csdn.net/u012533920/article/details/148457715?spm1011.2415.3001.5331 1.2、設置Hostname cat <<EOF > /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhos…

Vue基礎(14)_列表過濾、列表排序

Array.prototype.filter()【ES5】 filter() 方法創建給定數組一部分的淺拷貝&#xff0c;其包含通過所提供函數實現的測試的所有元素。 語法&#xff1a; filter(callbackFn) filter(callbackFn, thisArg) 參數&#xff1a; callbackFn(回調函數)&#xff1a;為數組中的每個元…

ComfyUI 中如何使用 Depth ControlNet SD1.5

目錄 SD1.5 Depth ControlNet 簡介 Depth ControlNet 主要特點 SD1.5 Depth ControlNet工作流準備工作 1. 安裝必要插件 方式一:使用 ComfyUI Manager(推薦) 方式二:通過 git 安裝必要插件 方式三:手動安裝(不推薦) 2.1 下載工作流所需模型 2.2 模型存放位置 SD…

IoT/HCIP實驗-3/LiteOS操作系統內核實驗(任務、內存、信號量、CMSIS..)

文章目錄 概述HelloWorld 工程C/C配置編譯器主配置Makefile腳本燒錄器主配置運行結果程序調用棧 任務管理實驗實驗結果osal 系統適配層osal_task_create 其他實驗實驗源碼內存管理實驗互斥鎖實驗信號量實驗 CMISIS接口實驗還是得JlINKCMSIS 簡介LiteOS->CMSIS任務間消息交互…

mysql的分頁場景下,頁數越大查詢速度越慢的解決方法

一 問題描述 select * from table limit 0,10掃描滿足條件的10行&#xff0c;返回10行&#xff0c; 但當limit 99989,10的時候數據讀取就很慢,limit 99989,10的意思掃描滿足條件的99999行&#xff0c;扔掉前面的99989行&#xff0c;返回最后的10行&#xff0c;這樣速度就會很慢…

MDP的 Commands模塊

文章目錄 Isaac Lab Commands 模塊詳細指南&#x1f4cb; 模塊概述&#x1f3d7;? 模塊架構&#x1f3aa; 命令類型詳解1. &#x1f6ab; 空命令 (NullCommand)2. &#x1f3c3; 速度命令 (VelocityCommand)&#x1f3b2; 均勻分布速度命令 (UniformVelocityCommand)&#x1f…

全流程開源!高德3D貼圖生成系統,白模一鍵生成真實感紋理貼圖

導讀 MVPainter 隨著3D生成從幾何建模邁向真實感還原&#xff0c;貼圖質量正逐漸成為決定3D資產視覺表現的核心因素。我們團隊自研的MVPainter系統&#xff0c;作為業內首個全流程開源的3D貼圖生成方案&#xff0c;僅需一張參考圖與任意白模&#xff0c;即可自動生成對齊精確…