Table of Contents
React handles most of the DOM manipulation. When any updates to state or props occur, React automatically updates the DOM to reflect the changes. But sometimes, you need more control over the DOM and manually perform some DOM operations.
Every React/JSX element is a DOM element, after all. Using refs, we can access the desired DOM node and perform any DOM operation we like. It is useful for controlling the elements programmatically, like reading an attribute of an element, accessing some DOM API, etc
Creating Refs
Ref is merely short for DOM reference to an element/node. Before we can use a ref to update and control a DOM element, we need to initialize it.
To initialize a ref with an element, follow these two simple steps:
1. Create a ref instance
Use the createRef()
method from React which returns a ref instance. Store it in a variable or a class property so that it is accessible throughout the component.
import React from 'react' // for class components - create the ref inside the constructor() – use ‘this’ this.myRef = React.createRef() // for functional components – simply create the ref inside the function body const myRef = React.createRef()
2. Bind the ref instance to an element
Once you have created a ref instance, you can assign it to the desired element to control. Every React element accepts a ref attribute. We should pass the ref instance that we created to that particular element’s “ref” attribute.
// for class components - use 'this' <input type='text' ref={this.myRef} /> // for functional components <input type='text' ref={myRef} />
Now the element and the ref instance are connected. We are now ready to access the element’s DOM node in the next section.
Using Refs
After you have created and initialized the ref instance with an element, you can use it anywhere inside that component. All ref instances have a property named “current” that stores the reference to the element.
You can access the DOM element using the current property of the ref instance. // access the element inside a class component this.myRef.current // access the element inside a functional component myRef.current
You can apply any valid DOM properties and methods to the “current” property. You can use them on some method or event handler depending on your requirement.
Here are some examples for you:
// focus a form input this.myFormRef.current.focus() // click a button programmatically this.myButtonRef.current.click() // get the value of a form input (commonly used on form submit) this.myFormRef.current.value
Note that the “current” property is null in the beginning when a ref is created. The code image below shows the similarity of selecting a DOM element in React and Javascript.
Forwarding Refs
Can you define a ref in a parent component and use it to select an element from its child component? Yes.
A component is an encapsulated entity of React elements. It does not have any real DOM representation. This is why refs work only on React elements and not on components.
However, we can access an element of a child component using a ref belonging to a parent component. This is all possible by forwarding the refs from a parent component to a child component.
Here is the flow:
1. Create a ref in the parent component.
Parent.js const parentRef = React.createRef()
2. Pass the ref to the child component through a ref prop on it. Notice that we are passing the ref prop on a component and not an element.
Parent.js import Child from ‘./components/Child.js // inside JSX code <Child ref={parentRef} />
3. Receive the passed ref in the child component by wrapping it inside the React.forwardRef()
method.
Child.js import React from 'react' // your class or functional component definition… function Child() { // … } /** Child component must be wrapped in forwardRef() before exporting. forwardRef() takes a callback function that receives the props and the passed ref. Make sure to pass it to the defined component so that it can access it. **/ export default React.forwardRef((props, ref) => ( < Child { … props } parentRef = { ref } /> ))
4. Bind the received/forwarded ref with the desired child component element.
Child.js // class or functional component definition… function Child(props) { return ( {/* use the parentRef prop to bind to an element as before */} <input type='text' ref={props.parentRef } /> ) }
Doing this will allow you to control a child component’s element right from the parent component’s code. Now the parent component can access the input element of the child component through parentRef.current
.
Summary
We can access the reference to a DOM element through “refs” and use all the valid DOM properties and methods. It gives us full control over the elements and to do the things that are usually not possible by manipulating the state/props.
They are handy to work with canvas API, text and file inputs. However, according to the React team, it is bad to overuse “refs” as imperative and not declarative.