图像与设计
在渲染结构不同的组件之间共享有状态逻辑时,用 render…
当一个组件持有状态/数据、但渲染方式需要由使用方决定时,把「接收数据并返回 JSX 的函数」作为 prop(或 children)传入,由该组件调用并把数据回传,从而实现逻辑复用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在渲染结构不同的组件之间共享有状态逻辑时通用
解决思路
- 给需要复用的组件传入一个函数作为 `render` prop(或 `children` prop),该函数接收数据并返回 JSX,例如 `<Title render={() => <h1>I am a render prop!</h1>} />`。
- 让组件自身不实现渲染逻辑,只调用并返回该 prop,例如 `const Title = (props) => props.render();`。
- 记住 prop 不必叫 `render`:任何值是一个返回 JSX 的函数的 prop 都算 render prop。
- 由持有数据的组件把数据作为参数传给 render prop:在组件内部 `return props.render(data)`,使用方写成 `<Component render={data => <ChildComponent data={data} />} />`。
- 让接收 render prop 的有状态组件持有状态并回传:在 `Input` 内部用 `useState` 保存 value,在 JSX 中调用 `{props.render(value)}`,使用方写 `<Input render={(value) => (<><Kelvin value={value} /><Fahrenheit value={value} /></>)} />`,使兄弟组件拿到同一份数据。
- 作为替代方案,也可以把 state 提升到最近的公共祖先(如 `App`),用 props 把 `value` / `handleChange` 传给 `Input`、`Kelvin`、`Fahrenheit`;但要注意在大应用中状态变化会导致所有子组件(包括不消费该数据的子组件)重渲染,可能影响性能。
- 改用更简洁的 children-as-a-function 写法:不显式传 `render` prop,而是把函数作为 children 传入 `<Input>{(value) => (<><Kelvin value={value} /><Fahrenheit value={value} /></>)}</Input>`,组件内部改为调用 `{props.children(value)}`,使用方无需关心 render prop 的名字。
- 在大多数现代 React 代码中优先使用自定义 Hooks 而不是 render props(Hooks 同样能复用逻辑,且不产生 render prop 嵌套)。
- 当出现多层 render prop 嵌套(例如 `Mutation`/`Query` 层层包裹以获取多个 mutation/query)时,改用该库提供的 Hooks(如 `useQuery`)直接访问数据,以减少代码量和嵌套层级。
- 用 render prop 的显式传参规避 HOC 的问题:不自动合并 props,而是把要向下传的 props 全部列在 render prop 的参数列表里显式传给子组件,从而避免命名冲突和隐式 props。
- 用 render prop 把应用逻辑与组件渲染分离:有状态组件负责传数据,无状态组件只负责渲染数据。
- 只在不需要修改所接收数据的组件上使用 render prop(无法给 `render` prop 添加生命周期方法)。
适用边界 · 注意事项
- 当自定义 Hooks 可以替代该模式时(Hooks 提供同样的逻辑复用且没有 render prop 嵌套)。
- 当它导致 JSX 深层嵌套、变得难以阅读和维护时。
- 当共享逻辑简单到用一个普通工具函数或 hook 就足够时。