React中如何向children子组件传递绑定共享ref的组件?
实现方案
你要的灵活布局能力可以通过React标准的render props模式实现,不需要额外引入第三方库,全部用函数组件+Hooks即可完成。
首先改造顶层Commentable组件,将children作为函数执行,把提前绑定好ref的评论按钮、评论表单作为参数传入,所有评论相关的交互逻辑全部收敛在这个组件内部:
import { useRef } from "react"; export default function Commentable({ children }) { const textareaRef = useRef(); // 内部完成ref绑定,外部不需要感知传递逻辑 const triggerButton = <CommentableButton formRef={textareaRef} />; const commentForm = <CommentForm formRef={textareaRef} />; // 执行children函数,传入可自由放置的节点 return <>{children({ button: triggerButton, form: commentForm })}</>; } export function CommentableButton({ formRef }) { const focusForm = (e) => { e.preventDefault(); // 加可选链避免ref未挂载时的报错 formRef.current?.focus(); } return <a href="#" onClick={focusForm}>Comment</a> } export function CommentForm({ formRef }) { return <textarea ref={formRef}></textarea> }
使用时,Commentable的子元素需要写成函数形式,从参数中解构出button和form节点,就可以在任意位置放置这两个元素,自由调整布局:
<Commentable> {({ button, form }) => ( <div className="card"> <div className="card-body"> <h5>Media Title</h5> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur nec enim id dolor elementum imperdiet. Phasellus luctus ante elit, ac egestas diam posuere at.</p> <hr /> {button} </div> <div className="card-footer"> {form} </div> </div> )} </Commentable>
方案说明
- 所有评论相关的逻辑(ref传递、聚焦、后续可扩展的评论提交、列表加载、权限校验等)全部收敛在
Commentable组件内部,业务侧使用时只需要关心布局位置,不需要重复实现交互逻辑 - 注意JSX语法中HTML的
class属性需要替换为className,否则会有控制台警告 - 给
focus调用增加了可选链判断,避免组件初次渲染阶段ref还未完成挂载时抛出空对象错误 - 如果后续需要扩展更多能力,比如暴露评论提交方法、加载状态,只需要在
children调用时多传入对应的参数即可,不需要改动已有的业务使用代码
内容的提问来源于stack exchange,提问作者NicholasJohn16
相关产品推荐
相关产品推荐

