React Forwarding Refs
Overview
React forwarding refs is a concept in React that allows the parent to pass down its component refs to their children. This method helps the child components modify elements from any location where the reference element is used.
Introduction
React forwarding refs is a concept in React that allows the parent to pass down its component refs to their children. Moving down (or forwarding) references to child components allow child component to read and modify their parent elements. This method helps the child components modify elements from any location where the reference element is used.
How does ForwardRef Work in React?
We typically use props to pass data down to the children component from parent components in React. Let us suppose we create a child component with its new set of props. To change the behavior of the child component without using states to avoid unnecessary re-rendering of the components, we need a way that can be refs in this case.
A DOM node can be accessed using refs, and we can change these refs (or DOM elements) without affecting the component states and avoiding re-rendering the entire component.
For the child node to access elements of the parent node, the parent component must have a way to pass down its refs to child components. The technique to pass down refs is known as ref forwarding.
Syntax:
Parameter:
The function takes two parameters, i.e., props and ref arguments.
Return value:
The function returns a JSX Element that gets displayed on the React app.
Working with Refs in Class Components
Creating Refs in React
Refs work similarly to states in React because when a component is constructed, refs are assigned to properties of the instance component, which ensure the element can be accessed from anywhere in the component. React provides a method React.createRef() to create refs. Once a ref is created, it can be attached to React element using ref attributes.
Here, we have created a Ref by the name newRef. To attach a ref to an element, we pass it as a value to the ref attributes of the element.
We have attached our ref newRef to the div element; this enables us to update the element without changing the component states.
Attaching Refs
Refs are created when the component is rendered and can be defined in either constructor() or componenetDidMount(). Refs can be attached to class components and DOM elements but cannot be attached to function components as they do not have an instance.
All Ref defined by the user represents a node, and to reference the entire node inside the render() function, React provides a current attribute to reference the node.
Refs receive different objects in their current property when it is attached to a class component or a DOM element:
- When a ref is used to reference an HTML element, then the ref receives the DOM element as its current property.
- When the ref is used on a class component, the ref receives the mounted instance of the class component as its current property.
Using Refs with Function Components
As discussed in the previous section, refs can not be attached to function components in React mainly because the functional components do not have instances to which the ref can reference.
According to official React documentation, you can convert functional components to class-based components if it is necessary to attach refs to a functional component.
Conditional Refs
Instead of passing the default ref attribute, we can also pass functions to set the refs in react. The advantage of the approach is that we have greater control over when the refs are set and unset.
Forwarding Refs to DOM Components
Let us consider a simple React component to render native buttons.
Components in React hide their implementation details, including their output. So components using our component SuperButton will not be able to get a ref to the inner DOM element (button in our case). This approach prevents components from relying heavily on each other components HTML elements. But sometimes, we want to rely on changing DOM elements, for example, managing focus in our component SuperButton.
Forwarding refs allow components to take a ref they receive and pass it to their children. For example, look at the following snippet:
Here, the ref passed to the SuperButton component is passed further down to its child. This gives access to the HTML element of the SuperButton component to other components that use it. They can access the DOM button directly as ref.current will point to the <button> element.
Forwarding Refs in Higher-order Components
Higher-Order Components can greatly benefit from ref forwarding. Let's see how:
The Logger component does not affect the rendering of components. Let us apply the HOC on our button component, SuperButton.
Now we import our component and apply a reference to it.
One thing to note here is that the refs are not props; this means refs passed to our SuperButton component, which is a HOC now, will not be passed down to the DOM element because refs are not props. Here the reference will be attached to the logger HOC.
To avoid such cases, we can forward refs to inner components (SuperButton in our case) using the forwardRed method like:
Here, the React.forwardRef receives props and ref parameters separately and returns a React.node.
Use-cases
Refs help control HTML elements without changing the states of a react component. There are many use cases where Ref forwarding can help. Let us see some of the cases where refs can help accomplish a variety of tasks:
Managing focus:
We often want to draw users' attention by changing the cursor focused on the object when the user clicks on a button. To achieve this, it makes more sense to focus on an element using refs instead of changing the states of the component. This is because changing the component states cause the complete component to re-render every time.
Text selection:
Similar to changing focus on clicking a button, to get the value from input flags, it is better to use a ref to reference the input HTML tag and get the current value using the ref from the input when needed instead of using states to store the value of a text selection and changing it every time the user changes the value of the text component.
Media playback:
Refs can control the music state on a react app that makes music pause, play, and stop without causing the component to re-render anytime a button is clicked or the component state is changed.
Triggering imperative animations:
Refs can also be used to start/trigger animations between elements that don't rely on their state but exist in different components, which will also require the need to use ref forwarding.
Displaying a Custom Name in DevTools
The React.forwardRef method accepts a render function used by the React DevTools to determine what needs to be displayed for the ref forwarding component.
Let us understand this with an example:
React DevTools shows the above component as "ForwardedRef", and if we name our render function, the DevTools identifies and also includes its name like:
Here, the DevTools shows the following component as "ForwardedRef(testFunction)".
We can set the function displayName property also to be included in the component we are wrapping like:
Conclusion
- React forwarding refs is a concept in React that allows the parent to pass down its component refs to their children.
- Refs work similarly to states in React because when a component is constructed, refs are assigned to properties of the instance component, which ensure the element can be accessed from anywhere in the component.
- Refs can be attached to class components and DOM elements but cannot be attached to function components as they do not have an instance.
- Different user cases of refs and forwarding refs are:
- Managing focus, media playback, and text selection.
- Triggering imperative animations.
- Changing HTML elements without causing re-rendering of components.
- We can also pass functions to set the refs in react to components. The advantage of the approach is that we have greater control over when the refs are set and unset.
- React DevTools displays the name for the ref forwarding component and can be changed with the help of the render function in React.forwardRef.