一文搞定 React 組件通信技巧
在 React + TypeScript 開發(fā)中,組件通信 是一個核心問題。不同的場景需要不同的通信方式,比如父子組件傳值、兄弟組件共享狀態(tài)、跨層級組件通信等。本文詳細介紹 6 種 React 組件通信方式,幫助你靈活應(yīng)對各種需求。
第一種,父組件向子組件傳值(Props)
適用場景:父組件需要向子組件傳遞數(shù)據(jù)。
實現(xiàn)方式:通過 props 傳遞數(shù)據(jù),并定義類型。
// 父組件
function Parent() {
const message: string = "Hello from Parent!";
return <Child message={message} />;
}
// 子組件 Props 類型
interface ChildProps {
message: string;
}
// 子組件
function Child({ message }: ChildProps) {
return <h1>{message}</h1>; // 輸出: Hello from Parent!
}參數(shù)解構(gòu):直接從ChildProps中解構(gòu)出message屬性,簡化代碼
渲染邏輯:將message的值作為<h1>標簽的內(nèi)容輸出,實現(xiàn)父組件向子組件的數(shù)據(jù)傳遞。
數(shù)據(jù)流動:父組件通過屬性將message傳遞給子組件,子組件通過Props接收并渲染,形成單向數(shù)據(jù)流。
這里推薦使用interface 定義props的類型,確保類型安全。 同時也具有可擴展性, 若需新增Props,只需在ChildProps中添加屬性,無需修改組件邏輯。
第二種, 子組件向父組件傳值(回調(diào)函數(shù))
適用場景:子組件需要向父組件傳遞數(shù)據(jù)(如表單提交、按鈕點擊)。
實現(xiàn)方式:父組件傳遞回調(diào)函數(shù),子組件調(diào)用并傳值。
// 父組件
function Parent() {
const handleChildData = (data: string): void => {
console.log("Data from Child:", data); // 輸出: Data from Child: Hello from Child!
};
return <Child onSendData={handleChildData} />;
}
// 子組件 Props 類型
interface ChildProps {
onSendData: (data: string) => void;
}
// 子組件
function Child({ onSendData }: ChildProps) {
const sendData = (): void => {
onSendData("Hello from Child!");
};
return <button onClick={sendData}>Send Data</button>;
}handleChildData 是父組件準備的一個"收件箱",通過 onSendData={handleChildData} 把這個"收件箱"交給子組件使用;
onSendData:(data:string)=>void;函數(shù)定義了子組件給父組件發(fā)送數(shù)據(jù)的具體實現(xiàn)。在子組件里面再定義一個函數(shù)來調(diào)用發(fā)送數(shù)據(jù)的函數(shù)。
第三種, 兄弟組件通信(狀態(tài)提升)
適用場景:兩個兄弟組件需要共享數(shù)據(jù)。
實現(xiàn)方式:將共享狀態(tài)提升到父組件,然后通過 `props` 傳遞。
// 父組件
function Parent() {
const [sharedData, setSharedData] = useState<string>("Initial Data");
return (
<div>
<SiblingA data={sharedData} />
<SiblingB onUpdateData={setSharedData} />
</div>
);
}
// 兄弟組件A Props 類型
interface SiblingAProps {
data: string;
}
// 兄弟組件A(顯示數(shù)據(jù))
function SiblingA({ data }: SiblingAProps) {
return <p>Data from SiblingB: {data}</p>;
}
// 兄弟組件B Props 類型
interface SiblingBProps {
onUpdateData: (data: string) => void;
}
// 兄弟組件B(更新數(shù)據(jù))
function SiblingB({ onUpdateData }: SiblingBProps) {
return (
<button onClick={() => onUpdateData("Updated Data")}>
Update Data
</button>
);
}使用 useState 管理共享狀態(tài),并明確定義傳輸?shù)臄?shù)據(jù)的 props 類型。
第四種, 跨層級組件通信(Context API)
適用場景:深層嵌套組件需要共享數(shù)據(jù),避免層層傳遞 `props`。
實現(xiàn)方式:使用 `React.createContext` 和 `useContext`,并定義 Context 類型。
// 1. 定義 Context 類型
interface ThemeContextType {
theme: string;
setTheme: (theme: string) => void;
}
// 2. 創(chuàng)建 Context(提供默認值)
const ThemeContext = React.createContext<ThemeContextType>({
theme: "light",
setTheme: () => {},
});
// 父組件(Provider)
function App() {
const [theme, setTheme] = useState<string>("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<ChildComponent />
</ThemeContext.Provider>
);
}
// 子組件(Consumer)
function ChildComponent() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<div>
<p>Current Theme: {theme}</p>
<button onClick={() => setTheme("dark")}>Toggle Theme</button>
</div>
);
}在父組件中,作為消息發(fā)送者
Provider 包裹需要訪問這些狀態(tài)的子組件,value 屬性傳遞當(dāng)前狀態(tài)和更新函數(shù)
在子組件中,作為消息消費者
使用 useContext 鉤子獲取 Context 值
可以直接使用 theme 和 setTheme
點擊按鈕會調(diào)用 setTheme 更新全局主題
第五種, 全局狀態(tài)管理(Redux / Zustand)
適用場景:大型應(yīng)用,多個組件需要共享復(fù)雜狀態(tài)。
實現(xiàn)方式(以 Zustand 為例): 從0死磕全棧第五天:React 使用zustand實現(xiàn)To-Do List項目
第六種 ,Refs 直接訪問子組件
適用場景:父組件需要直接調(diào)用子組件的方法。
實現(xiàn)方式:`useRef` + `forwardRef` + `useImperativeHandle`,并定義 Ref 類型。
// 1. 定義 Ref 類型
interface ChildRef {
increment: () => void;
}
// 2. 子組件
const Child = forwardRef<ChildRef>((props, ref) => {
const [count, setCount] = useState<number>(0);
useImperativeHandle(ref, () => ({
increment() {
setCount(count + 1);
},
}));
return <p>Child Count: {count}</p>;
});
// 3. 父組件
function Parent() {
const childRef = useRef<ChildRef>(null);
return (
<div>
<Child ref={childRef} />
<button onClick={() => childRef.current?.increment()}>
Increment from Parent
</button>
</div>
);
}執(zhí)行流程
父組件創(chuàng)建 childRef 并傳遞給子組件
子組件通過 useImperativeHandle 暴露 increment 方法
父組件按鈕點擊時,通過 childRef.current.increment() 調(diào)用
子組件內(nèi)部狀態(tài)更新,重新渲染顯示新計數(shù)
選擇建議
- 簡單數(shù)據(jù)流 → Props / 回調(diào)函數(shù)
- 兄弟組件共享 → 狀態(tài)提升 / Context
- 全局狀態(tài) → Redux / Zustand
- 跨層級通信 → Context
- 直接操作子組件 → Refs
結(jié)語
通信的終極目標不是傳遞數(shù)據(jù),而是構(gòu)建理解——讓每個組件在正確的時間,以正確的方式,做正確的事。
























