How many times has it happened when you are working on a React application and you want the parent component to interact with their children? It’s quite a common thing to handle the parent-child relationship inside a single component.
Usually, the most common approach is to use props. You can then use them with new props to re-render components. But what if you want to access DOM nodes or elements? Here’s where React Refs come into play. All the react native companies have refs as part of their arsenal, and you should too. Let’s learn more about it.
What are React Refs?
- ReactRefs provide access to DOM nodes or React elements created in the render method.
This is highly useful when you need to modify a child component outside of the typical React dataflow with props. Refs provide you with a cool alternative when the child is a DOM element or an instance of another React component.
Where Refs are used?
Refs are a great addition to the React ecosystem but you should not use them where anything can be done declaratively. Other than that there are some of the following use cases of React Refs:
Managing the focus state, text selection, or media playback.
While adding animations crucial to your application context.
Using it with some third-party DOM libraries.
How to use React Refs?
It’s time to write some code! But first, let’s see how we can create Refs in general. You can create a new Ref using React.createRef() API and then attach it to the elements via the ref attribute. Here’s a simple example where myRef is used in a class component:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
Now let’s take a look at one realistic example. Let’s say we need to grab a node element. For that, we can write a React class component as:
class MyButton extends React.Component {
render() {
const { btnLabel, btnAction } = this.props
return (
//..
<button onClick={btnAction}>{btnLabel}</button>
)
}
}
As you can see, we used props here but the <button> in JSX here is called as React.createElement('button') which is not exactly an HTML button element. Instead, we get a React element with this!
Now what to do to gain access to the actual HTML button element here? Yes, you use Refs to create a reference and then pass it to the element in JSX you want to. So the above class component now changes to:
class MyButton extends React.Component {
constructor() {
super()
this.btnRef = createRef()
}
render() {
const { btnLabel, btnAction } = this.props
return (
<button onClick={btnAction} ref={this.btnRef}>{btnLabel}</button>
)
}
}
Of course, we need a constructor to access the current context using this where we also define the btnRef ref. So now we have a way to access the actual HTML button element as this.btnRef.current.
Using Refs for focus control
This is one of the most common use cases of using React Refs. To achieve the focus of any element we can call the focus() method. If you have a custom input component then the ref attribute can be used to store a reference to the DOM node and the focus() method to explicitly focus the custom input element.
Here’s an example of the same:
class CustomInput extends React.Component {
constructor(props) {
super(props);
this.customInput = React.createRef();
this.focusCustomInput = this.focusCustomInput.bind(this);
}
focusCustomInput() {
this.customInput.current.focus();
}
render() {
return (
<div>
<input type="text" ref={this.customInput} />
<input type="button" onClick={this.focusCustomInput} />
</div>
);
}
}
In the above code, we first create a new ref to store the textInput DOM element. Make sure you notice that we are actually binding the custom input value with the current value passed by the user. Further, this goes to the focusCustomInput() method where we explicitly define to focus the input to access the current value to get the DOM node.
Now if you want to use the same concept with the React lifecycle methods like componentDidMount or componentDidUpdate then, we could use a ref to access the custom input calling the focusCustomInput() method manually:
class FocusInput extends React.Component {
constructor(props) {
super(props);
this.customInput = React.createRef();
}
componentDidMount() {
this.customInput.current.focusCustomInput();
}
render() {
return (
<MyCustomInput ref={this.customInput} />
);
}
}
Also Read: Using Data Grid component in MUI X with React
The case of forwardRef
These days web apps are primarily SPAs (Single Page Applications), they are more complex and we use plain HTML code very little in them. With that said, it becomes very easy to have more than one DOM node encapsulate more logic around the view behavior. Here's a quick example:
const LabelledInput = (props) => {
const { id, label, value, onChange } = props
return (
<div class="labelled--input">
<label for={id}>{label}</label>
<input id={id} onChange={onChange} value={value} />
</div>
)
}
export default LabelledInput
The issue arises when passing a ref to this component. Doing so will return its instance i.e. a React component reference and not the actual input element we want to focus on.
React does have a workaround here with forwardRef, this allows you to define internally what element the ref will point to. For this to work, we pass a second argument to the LabelledInput() function and place it to use on the desired input element. When the parent component passes a ref value, it will get the input which will be used to avoid exposing the properties of a component. Here’s our updated code:
const LabelledInput = (props, ref) => {
const { id, label, value, onChange } = props
return (
<div class="labelled--input">
<label for={id}>{label}</label>
<input id={id} onChange={onChange} value={value} ref={ref}/>
</div>
)
}
export default React.forwardRef(LabelledInput)
React Templates
We have learned about React Refs and where can be it used. If you are also looking for React Templates for Admin Dashboard or Webiste Landing Page Templates then here we have Modernize Templates for you:
Modernize Free React MUI Dashboard
Refs make it possible to access DOM nodes directly within React. One of the most common use cases can be found in using it when changing the child of a parent component. In this short tutorial, you got to know how to use it with forms while handling states in a class component. From here, you can read the following topics to better understand React Refs: