一文搞定 React 組件通信技巧
在 React + TypeScript 開發(fā)中,組件通信 是一個(gè)核心問題。不同的場景需要不同的通信方式,比如父子組件傳值、兄弟組件共享狀態(tài)、跨層級組件通信等。本文詳細(xì)介紹 6 種 React 組件通信方式,幫助你靈活應(yīng)對各種需求。
第一種,父組件向子組件傳值(Props)
適用場景:父組件需要向子組件傳遞數(shù)據(jù)。
實(shí)現(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>標(biāo)簽的內(nèi)容輸出,實(shí)現(xiàn)父組件向子組件的數(shù)據(jù)傳遞。
數(shù)據(jù)流動(dòng):父組件通過屬性將message傳遞給子組件,子組件通過Props接收并渲染,形成單向數(shù)據(jù)流。
這里推薦使用interface 定義props的類型,確保類型安全。 同時(shí)也具有可擴(kuò)展性, 若需新增Props,只需在ChildProps中添加屬性,無需修改組件邏輯。
第二種, 子組件向父組件傳值(回調(diào)函數(shù))
適用場景:子組件需要向父組件傳遞數(shù)據(jù)(如表單提交、按鈕點(diǎn)擊)。
實(shí)現(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 是父組件準(zhǔn)備的一個(gè)"收件箱",通過 onSendData={handleChildData} 把這個(gè)"收件箱"交給子組件使用;
onSendData:(data:string)=>void;函數(shù)定義了子組件給父組件發(fā)送數(shù)據(jù)的具體實(shí)現(xiàn)。在子組件里面再定義一個(gè)函數(shù)來調(diào)用發(fā)送數(shù)據(jù)的函數(shù)。
第三種, 兄弟組件通信(狀態(tài)提升)
適用場景:兩個(gè)兄弟組件需要共享數(shù)據(jù)。
實(shí)現(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`。
實(shí)現(xiàn)方式:使用 `React.createContext` 和 `useContext`,并定義 Context 類型。
// 1. 定義 Context 類型
interface ThemeContextType {
  theme: string;
  setTheme: (theme: string) => void;
}
// 2. 創(chuàng)建 Context(提供默認(rèn)值)
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ù)
在子組件中,作為消息消費(fèi)者
使用 useContext 鉤子獲取 Context 值
可以直接使用 theme 和 setTheme
點(diǎn)擊按鈕會(huì)調(diào)用 setTheme 更新全局主題
第五種, 全局狀態(tài)管理(Redux / Zustand)
適用場景:大型應(yīng)用,多個(gè)組件需要共享復(fù)雜狀態(tài)。
實(shí)現(xiàn)方式(以 Zustand 為例): 從0死磕全棧第五天:React 使用zustand實(shí)現(xiàn)To-Do List項(xiàng)目
第六種 ,Refs 直接訪問子組件
適用場景:父組件需要直接調(diào)用子組件的方法。
實(shí)現(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 方法
父組件按鈕點(diǎn)擊時(shí),通過 childRef.current.increment() 調(diào)用
子組件內(nèi)部狀態(tài)更新,重新渲染顯示新計(jì)數(shù)
選擇建議
- 簡單數(shù)據(jù)流 → Props / 回調(diào)函數(shù)
- 兄弟組件共享 → 狀態(tài)提升 / Context
- 全局狀態(tài) → Redux / Zustand
- 跨層級通信 → Context
- 直接操作子組件 → Refs
結(jié)語
通信的終極目標(biāo)不是傳遞數(shù)據(jù),而是構(gòu)建理解——讓每個(gè)組件在正確的時(shí)間,以正確的方式,做正確的事。















 
 
 






 
 
 
 