--- tags: [React, Component Communication, Props, Context, Frontend] create time: 2026-04-29 22:10 --- # 组件通信模式 ## 概述 React 中父子组件之间的数据流动有多种方式。理解每种模式的适用场景和性能影响,能够避免过度设计或通信瓶颈。本文档从简单到复杂,梳理完整的通信方案谱系。 ## 通信方向全景图 ```mermaid graph TD A["父 → 子"] --> B["Props(最基础)"] A --> C["Context Provider(跨层级)"] A --> D["状态管理库(全局共享)"] E["子 → 父"] --> F["回调 Prop(事件驱动)"] E --> G["refs(imperative)"] H["兄弟组件"] --> I["状态提升到共同父组件"] H --> J["通过共同祖先通信"] H --> K["状态管理库 / 发布订阅"] style B fill:#4FC08D,color:#fff style C fill:#F5A87D,color:#000 style F fill:#61DAFB,color:#000 ``` ## Props Drill(属性逐层透传) ### 问题场景 ```tsx function App() { const user = getUser(); return
; // Header 不需要 user,但深层的 Avatar 需要! } function Header({ user }) { return ( ); } ``` ### 解决方案对比 | 方法 | 适合场景 | 额外依赖 | |------|----------|---------| | **Context** | 少量深层传递(主题、用户信息) | 无 | | **自定义 Hook + Props 重组织** | 中等深度(3-4 层) | 无 | | **状态管理库** | 频繁变化、多组件共享 | Zustand/Redux | | **Render Prop / HOC** | 复用逻辑而非传值 | 无 | ## Callback Prop(子 → 父) ```tsx interface FormProps { onSubmit: (data: FormValues) => Promise; } function LoginForm({ onSubmit }: FormProps) { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const data = collectFormData(); onSubmit(data); // 通知父组件 }; return
; } // 父组件 function App() { const handleLogin = async (data: FormValues) => { await api.login(data); navigate("/dashboard"); }; return ; } ``` > [!note] 为什么不用 props.children 做通信? > children 是 UI 内容插槽,不是通信机制。通信用 callback prop 保持关注点分离。 ## Context 跨层级通信 ```tsx const UserContext = createContext(null); function UserProfile({ children }: { children: React.ReactNode }) { const user = useDatabaseUser(userId); return ( {/* Avatar、Settings、OrderHistory 任意深度都可消费 */} {children} ); } function OrderHistory() { const user = useContext(UserContext); // 直接获取,无需中间层透传 return
{user?.orders?.map(...)}
; } ``` > [!warning] Context 的性能陷阱 > - Provider value 对象每次渲染都是新引用 → 所有消费者重渲染 > - 解决:拆分 Context、或使用 `useReducer` 返回稳定的 `{state, dispatch}` 对象 ## 状态管理库方案 ```tsx // Zustand 方案:任意两个组件共享 state,无需祖先后代关系 import { create } from "zustand"; const useCartStore = create((set) => ({ items: [], addItem: (item) => set(state => ({ items: [...state.items, item] })), })); function ProductCard() { const addItem = useCartStore(s => s.addItem); return ; } function CartIcon() { const items = useCartStore(s => s.items); return {items.length}; } // 两者毫无关联,但共享同一份状态 ``` ## Ref Imperative API(命令式通信) ```tsx const formRef = useRef(null); function Parent() { const handleSubmit = () => { formRef.current?.validate(); // 命令子组件执行方法 formRef.current?.reset(); }; return <>; } const ChildForm = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ validate: () => validator.validate(), reset: () => setFields(initialValues), })); return
...
; }); ``` ## 决策树 ```mermaid graph TD A["需要通信?"] -->|"是"| B["通信范围?"] B --> C["仅父子两层"] B --> D["多层级穿透"] B --> E["跨层级 + 兄弟之间"] B --> F["需命令式调用子组件方法"] C --> G["Props + Callback ✅"] D --> H["Context ✅"] E --> I["Zustand / Redux ✅"] F --> J["forwardRef + useImperativeHandle ✅"] style G fill:#4FC08D,color:#fff style H fill:#61DAFB,color:#000 style I fill:#F5A87D,color:#000 style J fill:#A0AEC0,color:#000 ``` ## 关联笔记