组件之间怎么通信
Communication between components
一句话:五种,按「距离」从近到远选。
- 父 → 子:props。
- 子 → 父: 父把回调函数当 props 传下去, 子调用它。「事件往上报」就是这个。
- 兄弟之间:状态提升到共同父级, 再分别往下传(#345)。
- 跨很多层:Context—— 适合主题、当前用户、语言这种 「整棵树都要读、又不常变」的值。
- 全局、复杂、多处修改: 状态库(Redux / Zustand / Jotai) 或服务端状态库(TanStack Query)。
还有两个偏门但会问的:ref +useImperativeHandle(父组件主动调子组件的方法, 比如 focus()、play()); 以及 props.children(组合优于配置,也是解决 props drilling 的一招)。
会追问:「什么时候该上状态库?」—— 判据:同一份状态被很多不相关的组件读写、 或者需要时间旅行调试 / 中间件。只是「层数深」不该上 Redux, Context 或组合就够—— 这个回答比「大项目就用 Redux」好得多。
In one line: five ways, and you pick by distance — nearest first.
- Parent → child: props.
- Child → parent: the parent passes a callback down as a prop and the child calls it. That is all “events go up” means.
- Between siblings: lift the state to their common parent and pass it back down to each one (#345).
- Across many levels: Context — good for theme, current user, language: values the whole tree reads and that rarely change.
- Global, complex, written from many places: a state library (Redux / Zustand / Jotai) or a server-state library (TanStack Query).
Two less common ones they still ask about: ref plus useImperativeHandle (the parent calls a method on the child, say focus() or play()); and props.children (composition over configuration, which is also one answer to props drilling).
Follow-up: “When should you reach for a state library?” — the test: one piece of state is read and written by many unrelated components, or you need time-travel debugging or middleware. Depth alone is no reason for Redux — Context or composition is enough — that answer beats “big project, use Redux” by a mile.