您是否厭倦了 React 應用程式中無休止的 props 鑽取和回調鏈?管理深層嵌套組件之間的狀態和通訊是否感覺就像與義大利麵條程式碼搏鬥?
事件驅動架構可以簡化元件互動、降低複雜性並使您的應用程式更易於維護。在本文中,我將向您展示如何使用自訂 useEvent 掛鉤來解耦元件並改善 React 應用程式之間的通訊。
讓我帶您了解一下,讓我們從
開始在現代應用程式開發中,管理元件之間的狀態和通訊很快就會變得很麻煩。在涉及props 鑽探(其中資料必須透過多層巢狀元件向下傳遞)和回調鏈 的場景中尤其如此,這可能會導致邏輯混亂並使程式碼更難編寫維護或調試。
這些挑戰通常會創建緊密耦合的組件,降低靈活性,並增加試圖追蹤資料如何流經應用程式的開發人員的認知負擔。如果沒有更好的方法,這種複雜性會顯著減慢開發速度並導致脆弱的程式碼庫。
在典型的 React 應用程式中,父元件將 props 傳遞給子元件,子元件透過觸發回調與父元件進行通訊。這對於淺層組件樹來說效果很好,但隨著層次結構的加深,事情開始變得混亂:
Props 鑽取:資料必須透過多個層級的元件手動向下傳遞,即使只有最深層的元件需要它。
回呼鏈:同樣,子元件必須將事件處理程序沿樹向上轉發,創建緊密耦合且難以維護的結構。
以此場景為例:
隨著應用程式的成長,此設定變得更難管理。中間元件通常只是充當中間人,轉發 props 和回調,這使得程式碼變得臃腫並降低了可維護性。
為了解決道具鑽探,我們經常求助於全域狀態管理庫(例如Zusstand)等解決方案來簡化資料共享。但是如何管理回調呢?
這就是事件驅動方法可以改變遊戲規則的地方。透過解耦組件並依靠事件來處理交互,我們可以顯著簡化回調管理。讓我們探討一下這種方法是如何運作的。
事件驅動架構不是依賴直接回調在樹上進行通信,而是事件驅動的架構解耦組件並集中通信。其工作原理如下:
當SubChildren N觸發事件(例如onMyEvent)時,它不會直接呼叫Parent中的回調。
相反,它調度由集中式事件處理程序處理的事件。
事件處理程序偵聽調度的事件並處理它。
它可以通知父級(或任何其他感興趣的組件)或根據需要觸發其他操作。
道具仍然沿著層次結構傳遞,確保元件接收到它們運作所需的資料。
這個問題可以透過 zustand、redux 等集中式狀態管理工具來解決,但本文不會介紹。
但是,我們要如何實現這個架構?
讓我們建立一個名為 useEvent 的自訂鉤子,該鉤子將負責處理事件訂閱並傳回一個調度函數來觸發目標事件。
由於我使用的是 typescript,我需要擴充視窗事件介面才能建立自訂事件:
interface AppEvent<PayloadType = unknown> extends Event { detail: PayloadType; } export const useEvent = <PayloadType = unknown>( eventName: keyof CustomWindowEventMap, callback?: Dispatch<PayloadType> | VoidFunction ) => { ... };
透過這樣做,我們可以定義自訂事件映射並傳遞自訂參數:
interface AppEvent<PayloadType = unknown> extends Event { detail: PayloadType; } export interface CustomWindowEventMap extends WindowEventMap { /* Custom Event */ onMyEvent: AppEvent<string>; // an event with a string payload } export const useEvent = <PayloadType = unknown>( eventName: keyof CustomWindowEventMap, callback?: Dispatch<PayloadType> | VoidFunction ) => { ... };
現在我們定義了需要的接口,讓我們看看最終的鉤子代碼
import { useCallback, useEffect, type Dispatch } from "react"; interface AppEvent<PayloadType = unknown> extends Event { detail: PayloadType; } export interface CustomWindowEventMap extends WindowEventMap { /* Custom Event */ onMyEvent: AppEvent<string>; } export const useEvent = <PayloadType = unknown>( eventName: keyof CustomWindowEventMap, callback?: Dispatch<PayloadType> | VoidFunction ) => { useEffect(() => { if (!callback) { return; } const listener = ((event: AppEvent<PayloadType>) => { callback(event.detail); // Use `event.detail` for custom payloads }) as EventListener; window.addEventListener(eventName, listener); return () => { window.removeEventListener(eventName, listener); }; }, [callback, eventName]); const dispatch = useCallback( (detail: PayloadType) => { const event = new CustomEvent(eventName, { detail }); window.dispatchEvent(event); }, [eventName] ); // Return a function to dispatch the event return { dispatch }; };
useEvent 鉤子是一個自訂的 React 鉤子,用於訂閱和分派自訂視窗事件。它允許您監聽自訂事件並使用特定的負載觸發它們。
我們在這裡所做的非常簡單,我們使用標準事件管理系統並對其進行擴展以適應我們的自訂事件。
interface AppEvent<PayloadType = unknown> extends Event { detail: PayloadType; } export const useEvent = <PayloadType = unknown>( eventName: keyof CustomWindowEventMap, callback?: Dispatch<PayloadType> | VoidFunction ) => { ... };
好吧,很酷,但是,怎麼樣
查看此 StackBlitz(如果未加載,請在此處查看)
這個簡單的範例展示了 useEvent 掛鉤的用途,基本上,主體的按鈕正在調度從側邊欄、頁首和頁尾組件攔截的事件,並相應更新。
這讓我們可以定義因果反應,而無需將回呼傳播到許多組件。
以下是一些真實用例,其中 useEvent 掛鉤可以簡化 React 應用程式中的通訊並解耦元件:
通知系統通常需要全球通訊。
場景:
解決方案:使用 useEvent 掛鉤來調度帶有通知詳細資訊的 onNotification 事件。像NotificationBanner和Header這樣的元件可以監聽這個事件並獨立更新。
當使用者切換主題(例如,亮/暗模式)時,多個元件可能需要回應。
場景:
好處:不需要在整個組件樹上透過 props 傳遞主題狀態或回呼函數。
實作全域快速鍵,例如按「Ctrl S」儲存草稿或「Escape」關閉模式。
聊天應用程式或即時儀表板等應用程式需要多個元件來對即時更新做出反應。
對於具有多個部分的複雜表單,可以集中驗證事件。
追蹤使用者互動(例如按鈕點擊、導航事件)並將其傳送到分析服務。
對於共享白板或文件編輯器等協作工具,事件可以管理多用戶互動。
透過在這些場景中利用 useEvent 掛鉤,您可以建立模組化、可維護且可擴展的應用程式,而無需依賴深度嵌套的 props 或回調鏈。
事件可以透過降低複雜性和提高模組化來改變您建立 React 應用程式的方式。從小事做起——確定應用程式中的一些元件,這些元件將受益於解耦通訊並實現 useEvent 掛鉤。
透過這種方法,您不僅可以簡化程式碼,還可以使其在未來更易於維護和擴展。
為什麼要使用事件?
當您需要元件對應用程式中其他地方發生的事情做出反應,而不引入不必要的依賴項或複雜的回調鏈時,事件就會發揮作用。這種方法減少了認知負擔並避免了緊密耦合組件的陷阱。
我的推薦
使用事件進行元件間通訊-當一個元件需要通知其他元件有關操作或狀態變更時,無論它們在元件樹中的位置為何。
避免使用事件進行元件內通信,特別是對於密切相關或直接連接的元件。對於這些場景,依賴 React 的內建機制,如 props、state 或 context。
平衡的方法
雖然事件的力量很強大,但過度使用它們可能會導致混亂。明智地使用它們來簡化鬆散連接元件之間的通信,但不要讓它們取代 React 管理本地互動的標準工具。
以上是用於乾淨 React 元件通訊的事件驅動架構的詳細內容。更多資訊請關注PHP中文網其他相關文章!