If we ever need to work with a DOM element directly (as opposed to managing state via React), Refs are what we need!
What are Refs?
Refs allow us to access HTML elements directly. The Refs name is short for references. We can use them to setup a connection between a rendered element and our JS code.
What problems do Refs solve?
React asks us to work in certain ways – the React way of doing things (work with state and not the DOM, etc) – but in some cases it may not be possible or efficient to do so. Instead of ignoring those situations, the React team have actively built solutions to facilitate working around the typical React approach.
Refs are a good example of one of these solutions.
For instance, if you’re simply looking to simply read an input
‘s value or you want your input
field to receive focus, you may want to go against the typical React best practice of avoiding touching the DOM.
For the first example (reading an input
), the traditional React way would lead us to connect the value
attribute of that element to the component’s State for it to manage it (as opposed to us reading the value
directly from the element). This brings with it all the necessary code involved in state management, handling changes to the value, etc. However, what we’re trying to do is quite simple and this is potentially overkill.
By using Refs, we can more easily access the element (and its value
), meaning we don’t need to do state management and handle changes in the same way, resulting in less code that’s ultimately cleaner.
For the second example (focusing an input
), React doesn’t provide an easy way to focus an element and so you may need to work with the raw DOM API, and in order to do that you need to use the useRef()
hook.
How do Refs work?
For class components (now not recommended) we could use createRef()
, but with functional components we can create a Ref by using the useRef()
hook.
The Ref you created with useRef()
now always references that DOM node, which includes data like its current value
.
Example of Ref usage
Simply read an input
‘s value
import React, { useRef, Fragment } from "react";
const RefsExample1 = (props) => {
const textInput = useRef(null);
const handleClick = () => {
alert(textInput.current.value);
};
return (
<div>
<input type="text" ref={textInput} />
<input type="button" value="alert() the value" onClick={handleClick} />
</div>
);
};
export default RefsExample1;
Focusing an input
import React, { useRef } from "react";
const RefsExample2 = (props) => {
const textInput = useRef(null);
const handleClick = () => {
textInput.current.focus();
};
return (
<div>
<input type="text" ref={textInput} />
<input type="button" value="Focus the text input" onClick={handleClick} />
</div>
);
};
export default RefsExample2;
Controlled vs Uncontrolled Components
Where a component has state and you manage it, this is called a controlled component.
Where you don’t have state but may still interact with an element’s value (via Refs and regular JS, for example), this is what’s called an uncontrolled component. In this case, React is not controlling or managing the component’s data.