Search code examples
reactjs

How do I access refs of a child component in the parent component


If I have something like

<Parent>
  <Child1 />
  <Child2 />
  <Child3 />
</Parent>

And I want to access from Child2 where I have refs="child2refs", how can I do that?


Solution

  • Recommended for hooks-based React

    Ref forwarding is an opt-in feature that lets some components take a component reference they receive, and pass it further down (in other words, “forward” it) to a child.

    To do this, we need to make sure the child component has been decorated with the forwardRef function, and the parent needs to create refs using useRef and then pass that ref using the ref={ref} property.

    After mounting, the reference itself is reference to the child component, and reference.current points to the child component's

    import { forwardRef, useEffect, useRef } from "react";
    
    const LibraryButton = forwardRef((props, ref) => (
      <input type="text" {...props} ref={ref} placeholder="..."/>
    ));
    
    function autofocusClick(evt) {
      console.log("fancy!"); 
    }
        
    const AutoFocus = (props) => {
      const childRef = useRef();
    
      useEffect(() => childRef.current.focus(), []);
    
      return <LibraryButton onClick={autofocusClick} ref={childRef} />;
    }
    

    Recommended for class-based React (16.3 and newer)

    For older React code bases that don't use hooks, we need to use the createRef mechanism instead:

    import React from "react";
        
    const LibraryButton = React.forwardRef((props, ref) => (
      <input type="text" ref={ref} {...props} placeholder="..."/>
    ));
    
    function autofocusClick(evt) {
      console.log("fancy!"); 
    }
    
    class AutoFocus extends React.Component {
      constructor(props) {
        super(props);
        this.childRef = React.createRef();
      }
    
      componentDidMount() {
        this.childRef.current.focus();
      }
    
      render() {
        return <LibraryButton onClick={autofocusClick} ref={this.childRef} />;
      }
    }
    

    Forwarding refs HOC example

    Created Components are forwarding their ref to a child node.

    function logProps(Component) {
      class LogProps extends React.Component {
        componentDidUpdate(prevProps) {
          console.log('old props:', prevProps);
          console.log('new props:', this.props);
        }
     
        render() {
          const {forwardedRef, ...rest} = this.props;
     
          // Assign the custom prop "forwardedRef" as a ref
          return <Component ref={forwardedRef} {...rest} />;
        }
      }
     
      // Note the second param "ref" provided by React.forwardRef.
      // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
      // And it can then be attached to the Component.
      return React.forwardRef((props, ref) => {
        return <LogProps {...props} forwardedRef={ref} />;
      });
    }
    

    See Forwarding Refs in React docs.

    Recommended for React versions older than 16.3

    If it cannot be avoided the suggested pattern extracted from the React docs would be:

    import React, { Component } from 'react';
    
    const Child = ({ setRef }) => <input type="text" ref={setRef} />;
    
    class Parent extends Component {
        constructor(props) {
            super(props);
            this.setRef = this.setRef.bind(this);
        }
    
        componentDidMount() {
            // Calling a function on the Child DOM element
            this.childRef.focus();
        }
    
        setRef(input) {
            this.childRef = input;
        }
    
        render() {
            return <Child setRef={this.setRef} />
        }
    }
    

    The Parent forwards a function as prop bound to Parent's this. When React calls the Child's ref prop setRef it will assign the Child's ref to the Parent's childRef property.