React hooks - useContext

useContext

        • 用法
        • 使用
          • 以非侵入的方式使用 Context
          • 使用 useContext 重構 useReducer 案例

用法

實現多層組件的數據傳遞

  1. 在全局創建 Context 對象
  2. 在父組件中使用 Context.Provider 提供數據
  3. 在子組件中使用 useContext 使用數據
import React, { useContext } from 'react'
// 全局
const MyContext = React.createContext(初始數據)
// 父組件
const Father = () => {return <MyContext.Provider value={{name: 'escook', age: 22}}></MyContext.Provider>
}
// 子組件
const Son = () => {const myCtx = useContext(MyContext)return <div><p>姓名:{myCtx.name}</p><p>年齡:{MyCtx.age}</p></div>
} 
使用
// 聲明 TS 類型
type ContextType = { count: number; setCount: React.Dispatch<React.SetStateAction<number>> } 
// 1. 創建 Context 對象
const AppContext = React.createContext<ContextType>({} as ContextType) 
export const LevelA: React.FC = () => {// 定義狀態const [count, setCount] = useState(0)return (<div style={{ padding: 30, backgroundColor: 'lightblue', width: '50vw' }}><p>count值是:{count}</p><button onClick={() => setCount((prev) => prev + 1)}>+1</button>{/* 2. 使用 Context.Provider 向下傳遞數據 */}<AppContext.Provider value={{ count, setCount }}> {/* 使用子組件 */}<LevelB /></AppContext.Provider> </div>)
} 
export const LevelB: React.FC = () => {return (<div style={{ padding: 30, backgroundColor: 'lightgreen' }}>{/* 使用子組件 */}<LevelC /></div>)
} 
export const LevelC: React.FC = () => {// 3. 使用 useContext 接收數據const ctx = useContext(AppContext) return (<div style={{ padding: 30, backgroundColor: 'lightsalmon' }}>{/* 4. 使用 ctx 中的數據和方法 */}<p>count值是:{ctx.count}</p> <button onClick={() => ctx.setCount((prev) => prev + 1)}>+1</button><button onClick={() => ctx.setCount(0)}>重置</button> </div>)
}
以非侵入的方式使用 Context

保證父組件中代碼的單一性和Provider的通用性,解決父組件中侵入了 <AppContext.Provider> 的問題,
Context.Provider 封裝到獨立的 Wrapper 函數式組件中。

核心思路:每個 Context 都創建一個對應的 Wrapper 組件,在 Wrapper 組件中使用 Provider 向 children 注入數據。

// 聲明 TS 類型
type ContextType = { count: number; setCount: React.Dispatch<React.SetStateAction<number>> }
// 創建 Context 對象
const AppContext = React.createContext<ContextType>({} as ContextType)
// 定義獨立的 Wrapper 組件,被 Wrapper 嵌套的子組件會被 Provider 注入數據
export const AppContextWrapper: React.FC<React.PropsWithChildren> = (props) => {// 1. 定義要共享的數據const [count, setCount] = useState(0)// 2. 使用 AppContext.Provider 向下共享數據return <AppContext.Provider value={{ count, setCount }}>{props.children}</AppContext.Provider>
} 
import React from 'react'
import { AppContextWrapper, LevelA } from '@/components/use_context/01.base.tsx'const App: React.FC = () => {return (<AppContextWrapper><!-- AppContextWrapper 中嵌套使用了 LevelA 組件,形成了父子關系 --><!-- LevelA 組件會被當做 children 渲染到 Wrapper 預留的插槽中 --><LevelA /></AppContextWrapper>)
}
export default App 

組件樹的嵌套關系為:App => Wrapper => LevelA => LevelB => LevelC。因此在 LevelA、LevelB 和 LevelC 組件中,都可以使用 context 中的數據。

export const LevelA: React.FC = () => {// 使用 useContext 接收數據const ctx = useContext(AppContext)return (<div style={{ padding: 30, backgroundColor: 'lightblue', width: '50vw' }}>{/* 使用 ctx 中的數據和方法 */}<p>count值是:{ctx.count}</p><button onClick={() => ctx.setCount((prev) => prev + 1)}>+1</button><LevelB /></div>)
}
export const LevelC: React.FC = () => {// 使用 useContext 接收數據const ctx = useContext(AppContext)return (<div style={{ padding: 30, backgroundColor: 'lightsalmon' }}>{/* 使用 ctx 中的數據和方法 */}<p>count值是:{ctx.count}</p><button onClick={() => ctx.setCount((prev) => prev + 1)}>+1</button><button onClick={() => ctx.setCount(0)}>重置</button></div>)
}
使用 useContext 重構 useReducer 案例
// 1. 定義 Context 的 TS 類型
// 在這一步,我們必須先明確要向子組件注入的數據都有哪些
type UserInfoContextType = { user: UserType; dispatch: React.Dispatch<ActionType> } 
// 2. 創建 Context 對象
const UserInfoContext = React.createContext<UserInfoContextType>({} as UserInfoContextType) 
// 3. 創建 ContextWrapper 組件
export const UserInfoContextWrapper: React.FC<React.PropsWithChildren> = ({ children }) => {const [state, dispatch] = useImmerReducer(reducer, defaultState, initAction)return <UserInfoContext.Provider value={{ user: state, dispatch }}>{children}</UserInfoContext.Provider>
} 
import React from 'react'
import { UserInfoContextWrapper, Father } from '@/components/use_reducer/01.base.tsx'const App: React.FC = () => {return (<UserInfoContextWrapper><Father /></UserInfoContextWrapper>)
}export default App 
export const Father: React.FC = () => {// 4. 調用 useContext 導入需要的數據const { user: state, dispatch } = useContext(UserInfoContext)const changeUserName = () => dispatch({ type: 'UPDATE_NAME', payload: '劉龍彬' })return (<div><button onClick={changeUserName}>修改用戶名</button><p>{JSON.stringify(state)}</p><div className="father">{/* 5. 這里沒有必要再往子組件傳遞 props 了 */}{/* <Son1 {...state} dispatch={dispatch} /><Son2 {...state} dispatch={dispatch} /> */}<Son1 /><Son2 /></div></div>)
} 
const Son1: React.FC = () => {// 6. 把 props 替換為 useContext() 的調用const { dispatch, user } = useContext(UserInfoContext)const add = () => dispatch({ type: 'INCREMENT', payload: 1 })return (<div className="son1"><p>{JSON.stringify(user)}</p><button onClick={add}>年齡+1</button></div>)
} 
const Son2: React.FC = () => {// 7. 把 props 替換為 useContext() 的調用const { dispatch, user } = useContext(UserInfoContext)const sub = () => dispatch({ type: 'DECREMENT', payload: 5 })return (<div className="son2"><p>{JSON.stringify(user)}</p><button onClick={sub}>年齡-5</button><hr /><GrandSon /></div>)
} 
const GrandSon: React.FC = () => {// 8. 把 props 替換為 useContext() 的調用const { dispatch } = useContext(UserInfoContext)const reset = () => dispatch({ type: 'RESET' })return (<><h3>這是 GrandSon 組件</h3><button onClick={reset}>重置</button></>)
} 

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

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

相關文章

全網爆火Remini 粘土濾鏡風格,我用ComfyUI一鍵生成了(保姆級教程)!

一、火爆全網的Remini&#xff01; Remini真的火爆了&#xff01;最近大家的朋友應該都被粘土濾鏡刷屏了。 小紅書上粘土濾鏡、粘土特效的帖子動不動就是幾百萬瀏覽量&#xff0c;幾千贊。 在有些電商平臺上還有人接單&#xff0c;幫忙定制remini粘土風格的照片&#xff01; …

解釋瀏覽器緩存和本地存儲的區別,以及如何實現事件的防抖和節流

1:瀏覽器緩存和本地存儲的區別: 瀏覽器緩存:瀏覽器緩存是一種臨時性的數據存儲,用于提高網頁加載速度。緩存的數據存儲在內存或磁盤中,當用戶再次訪問相同的資源時,瀏覽器會優先從緩存中讀取數據,而不是從服務器重新請求。緩存的數據可以在瀏覽器關閉后自動清除,或者根據 HTT…

vue+three.js實現3d系統的搭建

1.首先node.js是12.22版本的&#xff0c;安裝three.js可以參考這篇文章 直接用Threejs入門-安裝教程_安裝three.js-CSDN博客 直接在終端安裝three.js即可 npm install --save three 在相同目錄下安裝vite構建工具 npm install --save-dev vite 在項目里面看package.json中…

神秘顧客調查:第三方渠道監測如何操作?

第三方渠道監測是指通過專業的第三方機構或服務商&#xff0c;對企業的銷售渠道進行系統化的監督和評估。這種監測幫助企業了解各渠道的表現&#xff0c;確保合規性&#xff0c;提升市場競爭力。深圳神秘顧客市場調查限公司&#xff08;SMS&#xff09;總結了第三方渠道監測的操…

【安裝筆記-20240528-Linux-在 Vultr 云服務器上安裝 OpenWRT】

安裝筆記-系列文章目錄 安裝筆記-20240528-Linux-在 Vultr 云服務器上安裝測試 OpenWRT 文章目錄 安裝筆記-系列文章目錄安裝筆記-20240528-Linux-在 Vultr 云服務器上安裝測試 OpenWRT 前言一、軟件介紹名稱&#xff1a;OpenWRT主頁官方介紹 二、安裝步驟測試版本&#xff1a…

多function-calling 調用

多function-calling 調用 接上一篇function-calling調用&#xff0c;本篇實現了一個多function-calling的調用。OpenAI會根據function的描述自己來判斷應該調用哪個function。最終調用function的動作是由我們來決定的&#xff0c;當然你也可以不調對應的函數。 兩個函數分別是…

案例研究|MeterSphere助力萬物云構建高效自動化測試平臺

萬物云空間科技服務股份有限公司&#xff08;以下簡稱為“萬物云”&#xff09;&#xff0c;前身為萬科物業發展股份有限公司&#xff0c;是國內領先的物管龍頭上市公司。作為一家科技引領的全域空間服務商&#xff0c;萬物云致力于打造產業級共享服務平臺&#xff0c;基于空間…

1. lambda初體驗

首先聲明一個函數式接口&#xff0c;就只接口內只有一個抽象方法 //函數式接口 public interface Factory {Object getObject();}接口實現類 public class SubClass implements Factory {Overridepublic Object getObject() {return new User();}}User類 public class User …

酒店提前線上訂房小程序源碼系統 PHP+MySQL組合開發 源碼開源可二開 帶完整的安裝代碼包以及搭建教程

系統概述 隨著移動互聯網的普及&#xff0c;越來越多的人習慣通過手機進行酒店預訂。傳統的線下訂房方式逐漸無法滿足用戶的需求&#xff0c;酒店提前線上訂房小程序的出現成為必然趨勢。該源碼系統的開發旨在為酒店提供一個便捷、高效的線上訂房平臺&#xff0c;提升用戶體驗…

基于微信小程序+ JAVA后端實現的【醫院掛號預約系統】 設計與實現 (內附設計LW + PPT+ 源碼+ 演示視頻 下載)

項目名稱 項目名稱&#xff1a; 《基于微信小程序的醫院掛號預約系統設計與實現》 項目技術棧 該項目采用了以下核心技術棧&#xff1a; 后端框架/庫&#xff1a; Java, SSM框架數據庫&#xff1a; MySQL前端技術&#xff1a; 微信小程序, uni-app 項目展示 全文概括 本…

設置單群聊消息擴展

根據消息 ID &#xff0c;對單聊會話或群聊會話中已經發送的消息設置擴展信息。每次最多可以設置 100 個擴展屬性信息&#xff0c;最多可設置 300 個。 通過 Server API 操作消息擴展&#xff0c;默認不會向操作者的客戶端同步&#xff0c;會導致擴展信息不一致。如有需要&…

MySQL觸發器實戰:自動執行的秘密

歡迎來到我的博客&#xff0c;代碼的世界里&#xff0c;每一行都是一個故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交給時間 &#x1f3e0; &#xff1a;小破站 MySQL觸發器實戰&#xff1a;自動執行的秘密 前言觸發器的定義和作用觸發器的定義和作用觸發器的…

大模型領域新聞跟蹤

楊值麟 月之暗面楊植麟&#xff1a;大模型開發是“承包森林”月之暗面集結最強創投&#xff0c;“清華師姐”是最強“助攻”月之暗面楊植麟&#xff1a;互聯網研發是“種樹”&#xff0c;大模型研發是“承包森林”月之暗面楊植麟復盤大模型創業這一年&#xff1a;向延綿而未知…

搜維爾科技:穿上Xsens Link動作捕捉套裝,進行精準的運動捕捉

穿上Xsens Link動作捕捉套裝&#xff0c;進行精準的運動捕捉 搜維爾科技&#xff1a;穿上Xsens Link動作捕捉套裝&#xff0c;進行精準的運動捕捉

vue 筆記01

目錄 01 vuejs中屬性的基本使用 02 v-show指令的使用 03 v-if 指令的使用 04 v-for指令的使用 05 v-model 指令 06 template模板標簽 07 v-on事件的綁定指令 08 事件中的event對象 01 vuejs中屬性的基本使用 {{ }} 叫做mustache模板語法 雙花括號 小胡子語法 雙花括號…

安卓手機APP開發__構建通話應用

安卓手機APP開發__構建通話應用 目錄 概述 依賴項和權限 注冊應用 平臺集成 注冊通話 添加通話 接聽來電 拒接來電 去電 將通話置于保持狀態 斷開連接 轉接音頻 前臺支持 Surface 支持 概述 使用 Telecom Jetpack 庫為用戶提供最佳視頻和音頻體驗。借助 Teleco…

GO語言 linux部署

https://blog.csdn.net/wangye135/article/details/136177171 一、簡述 1. 可以直接在服務器上運行編譯好的二進制文件&#xff0c;不需要在服務器上下載語言環境。 2. 內置運行時環境&#xff1a;可執行文件中內置了運行時環境&#xff0c;包括垃圾回收、調度器等&#xff…

Java深拷貝淺拷貝

在Java中&#xff0c;深拷貝和淺拷貝是兩種不同的對象復制方式。 淺拷貝&#xff1a;創建一個新對象&#xff0c;然后將原對象的非靜態字段復制到新對象中。如果字段是值類型的&#xff0c;那么對該字段執行逐位復制。如果字段是引用類型的&#xff0c;則復制引用但不復制引用的…

SAP 根據報錯消息號快速定位問題

通常用戶在業務的操作過程中&#xff0c;經常會遇到報錯信息&#xff0c;有些報錯是系統控制拋出的信息&#xff0c;但是有些報錯的信息是根據不同地點業務場景對填寫的數據進行判斷校驗&#xff0c;然后給出的報錯信息&#xff0c;正常情況報錯信息一般是有文本&#xff0c;或…

【C語言】文件操作講解

C語言文件操作講解 文件文件名文件類型數據在內存中的存儲 文件緩沖區文件指針文件的打開與關閉fopenfclosefopen與fclose的使用文件的打開方式 文件的順序讀寫fputcfgetcfputsfgetsfprintffscanffwritefread輸入流與輸出流對比scanf\fscanf\sscanf與printf\fprintf\sprintfssc…