如何在View组件中访问多层嵌套的GreatGrandChild组件?
如何在View组件中访问嵌套的GreatGrandChild组件?
我需要在View组件中访问GreatGrandChild组件。
View组件:
<View> <Child> .... </Child> </View>
Child组件:
<Child> <GrandChild> .... </GrandChild> </Child>
GrandChild组件:
<GrandChild> <GreatGrandChild> .... </GreatGrandChild> </GrandChild>
GreatGrandChild组件:
<GreatGrandChild ref={(component) => { this.component = component; }}> .... </GreatGrandChild>
我该如何在View组件中访问GreatGrandChild组件?能否使用refs来实现?哪种生命周期方法最为合适?
当然可以用refs实现,这里提供两种可行方案,还有对应的生命周期建议:
方案一:用Ref转发(React.forwardRef)—— 最优雅的方式
这种方法不需要逐层手动传递ref,React官方也推荐这种嵌套组件间传递ref的方式。你需要从最上层到目标组件逐层转发ref:
- 改造GreatGrandChild组件:如果是函数组件,必须用
React.forwardRef包裹才能接收ref;类组件可以直接接收ref:
// 函数组件版本 const GreatGrandChild = React.forwardRef((props, ref) => { return <div ref={ref}>GreatGrandChild内容</div>; }); // 类组件版本无需forwardRef,直接定义即可 class GreatGrandChild extends React.Component { // 组件逻辑 }
- 改造GrandChild组件,把收到的ref转发给GreatGrandChild:
const GrandChild = React.forwardRef((props, ref) => { return <GreatGrandChild ref={ref} {...props} />; });
- 改造Child组件,同样转发ref给GrandChild:
const Child = React.forwardRef((props, ref) => { return <GrandChild ref={ref} {...props} />; });
- 在View组件中使用ref:
class View extends React.Component { constructor(props) { super(props); this.greatGrandChildRef = React.createRef(); } componentDidMount() { // 这里就能直接拿到GreatGrandChild的实例/ DOM元素了 console.log(this.greatGrandChildRef.current); } render() { return <Child ref={this.greatGrandChildRef} />; } }
方案二:逐层手动传递ref(适合简单场景,不推荐复杂嵌套)
如果不想用forwardRef,你可以给每一层组件加一个自定义props来传递ref:
- View组件创建并传递ref:
class View extends React.Component { constructor(props) { super(props); this.greatGrandChildRef = React.createRef(); } componentDidMount() { console.log(this.greatGrandChildRef.current); } render() { return <Child greatGrandChildRef={this.greatGrandChildRef} />; } }
- Child组件把ref传给GrandChild:
class Child extends React.Component { render() { return <GrandChild greatGrandChildRef={this.props.greatGrandChildRef} />; } }
- GrandChild组件把ref传给GreatGrandChild:
class GrandChild extends React.Component { render() { return <GreatGrandChild ref={this.props.greatGrandChildRef} />; } }
关于生命周期方法的选择
- 类组件:优先用
componentDidMount,因为此时所有嵌套组件都已经挂载完成,ref的current属性已经指向目标组件实例/DOM。如果需要在组件更新后访问,用componentDidUpdate,但要注意加判断避免重复执行(比如判断ref是否存在、是否是首次渲染)。 - 函数组件:用
useEffect钩子,依赖项传空数组就相当于componentDidMount的效果:
function View() { const greatGrandChildRef = useRef(null); useEffect(() => { console.log(greatGrandChildRef.current); }, []); return <Child ref={greatGrandChildRef} />; }
小提醒
尽量不要过度依赖refs,优先用props和状态提升来实现组件间通信。只有当你需要直接操作DOM或者调用子组件实例方法时,再考虑用refs哦。
内容的提问来源于stack exchange,提问作者Sunny
相关产品推荐
相关产品推荐

