We’ll be talking about Refs in this section. We’ll cover the following
- Refs Overview
- Example – Creating Refs
- Example – Retrieving the Input Value
- Refs in Class Component
- Ref Forwarding
1. Refs Overview
Recall that in a previous lesson, where we covers Form Handling, we learnt that you can interact with input elements by binding it to a handler that updates its value via the state. However, Refs make is possible to access DOM nodes directly within React.
According the the React documentations, you can use Refs to:
- Manage focus, select text and manage media playback
- trigger imperative animations
- integrate with 3rd party DOM libraries
2. Example – Creating Refs
In this example, will uses a Ref to focus a text input. To achieve this, we take three steps:
- create a ref using React.createRef() method
- attach the ref to the input element using the ref attribute
- call the focus method on the input element. This is done in the ComponentDidMount() lifecycle method
The ref holds a reference to the input element. The complete code is given below
export class RefDemo extends Component { constructor(props) { super(props) //Create a Ref this.inputRef = React.createRef() } componentDidMount(){ this.inputRef.current.focus(); } render() { return ( <div> <input type="text" ref={this.inputRef}></input> </div> ) } } export default RefDemo
In this example, once the component mounts, the focus is set on the input element.
3. Example- Retrieving the Input Value
Here we would use a button to retrieve the input value of the text field. The code is quite clear, so I’ll not go over it. See below:
getValue = () => { alert(this.inputRef.current.value) } render() { return ( <div> <input type="text" ref={this.inputRef} ></input> <button onClick={this.getValue}>Get Input</button> </div> ) }
So, when you click the button, an alert box is displayed with the value of the textfield.
Callback Ref – This is an older way of creating ref. For all practical purposes at this time you likely will not be using it. So I’ll not cover it. However, if you are curious, then read it up here.
4. Example – Ref in Class Component
In the previous example, we added Ref to a button. Now we would see how to add Ref to a component. So basically, a parent component attaches a Ref as attribute to a child component.
First we have a parent component with a button and a child component with a textfield. When the button in the parent component is clicked, the textfield in the child component receives the focus.
To achieve this, you pass the parent’s ref to the child component
So in the parent component, FocusInput, we have
clickHandler = () => { this.componentRef.current.focusInput() } render() { return ( <div> <Input ref={this.componentRef}></Input> <button onClick={this.clickHandler} >Focus Input</button> </div> ) }
And in the child component, Input, we have:
focusInput(){ this.inputRef.current.focus() } render() { return ( <div> <input ref={this.inputRef} type="text"></input> </div> ) }
It’s necessary to note that this example will only work with class components.
5. Ref Forwarding
This allows us to work with Refs with functional component. Here, the parent component will be a class component while the child component is a functional component. Here, the parent component will directly reference the element in the child component. To achieve this follow these steps:
- create a Ref in the parent component
- attach the ref to the child component using the ref attribute
- forward this ref to the input element in the child component using the fowardRef() method from the React library
- define the click handler in the parent component
In order for the child component to receive a ref, the component must be created using React.fowardRef(). This method takes the functional component as first parameter. This function noramally would be defined as an arrow function like this:
() => { functionbody }
Then this functional component take two parameters. The first is props, and the second is the ref attribute. This ref is now given as value to the ref attribute of the HTML element. So we can now refactor the functional component to be like this:
const FRInput = React.forwardRef((props, ref) => { return ( <div> <input type="text" ref={ref}></input> </div> ) })
Then the parent component markup looks like shown below:
render() { return ( <div> <FRInput ref={this.inputRef}></FRInput> <button onClick={this.clickHandler}>Focus Input</button> </div> ) }