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?
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} />;
}
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} />;
}
}
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.
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.