This is the sixth article of React Hooks series. If you haven't read the first five articles, you can find them at the links below.
- useContext hook and context API
- useCallback annd useMemo hooks
- useEffect hook
- useReducer hook
- useState hook
Content Outline
- Introduction to useRef hook
- Purpose of useRef hook
- Accessing DOM elements using useRef hook
- Persisting values between re-render of component
- Using ref with class Components
- Summary
- References
What is useRef hook?
A hook is a special function which enables one use state and other React features without writing ES6 class components which are generally considered difficult to understand, use and master.
useRef
hook is part of the React Hooks API. It is a function which takes a maximum of one argument and returns an Object
. The returned object has a property called current
whose value is the argument passed to useRef
. If you invoke it without an argument, the returned object's current
property is set to undefined
. The code below illustrates how to invoke the useRef
hook in functional components.
const myRef = React.useRef(null);
// You can use a descriptive variable name instead of myRef.
myRef
, which is returned by a call to useRef
hook is an object which looks like {current: null}
. If invoked without an argument, then the returned object is {current: undefined}
What purpose does useRef hook serve?
Some of the use cases of useRef
hook are:
- To access DOM elements
- To persist values in successive renders
Accessing DOM elements
One of the most common use case of useRef
hook is to access DOM elements (NOT custom React component). For example if you want to access an input
element after it has been mounted to the DOM, instead of using document.getElementById, document.querySelector
or any other method
for selecting DOM
elements like in vanilla javascript
, you can use useRef
hook. This is illustrated in the example below.
import React from "react";
import ReactDOM from "react-dom";
const App = (props) => {
const inputRef = React.useRef(null);
React.useEffect(() => {
console.log(inputRef.current);
inputRef.current.focus();
}, []);
return (
<form>
<input
type="text"
placeholder="Enter Name"
name="name"
ref={inputRef} />
</form>
);
};
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
In the code above, App
component returns a form
element. useRef
hook is invoked and null
is passed as an argument. useRef
returns an object, {current: null}
which is assigned to inputRef
. inputRef
is an object whose current
property is initially set to null
. Since it is passed as value of input
element's ref
attribute, the value
of current
property is then set to input
DOM element. input
element can then be accessed and manipulated via inputRef
's current property.
WARNING
Though
useRef
makes it easy to manipulate DOM elements, you are discouraged from using it willynilly. There are specific use cases where it is advisable to useuseRef
hook. Read more about them at
React Documentation.
To persist values in successive renders
There are situations where you might want to persist certain values in consecutive renders. Instead of storing these values in state which might cause unnecessary renders, you can store it as the value of useRef
's current property since react guarantees that this value is persisted between re-renders. Furthermore, if you want to determine state value from previous state values, it is advisable to use useRef
hook to persist them. This is very helpful because in functional components, state is not merged but completely replaced.
Using ref with class components
It should be noted that useRef
hook is available only for functional components. If you want to reference a DOM element in class components, you can use React.createRef
API. Like the useRef
hook in functional components, React.createRef
takes a maximum of one argument and returns an object with current
property set to the argument passed and undefined
if no argument is passed. The object returned by creatRef
is stored in an instance property during construction like this.myRef = React.createRef()
.
class App extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef(null);
}
componentDidMount() {
console.log(this.inputRef.current);
this.inputRef.current.focus();
}
render() {
return (
<form>
<input
type="text"
placeholder="Enter Name..."
name="name"
ref={this.inputRef} // or ref = {e => this.inputRef.current = e}
/>
</form>
);
}
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
The object returned by calling React.createRef
is assigned as value of ref
attribute of the DOM element we want to reference. You can also achieve the same thing by using:
ref = {element => this.inputRef.current = element}
instead of ref={this.inputRef}
.
NOTE
It is worth pointing out that
createRef
anduseRef
hook can be used for creatingref
in functional components. However,ref
s created usingcreateRef
are not persisted between re-renders. A new ref is always created whenever the component is re-rendered.You should also note that React will not be notified of any changes to a component's
ref
.
Summary
In summary, this article looked at:
- An overview of hooks and the React Hooks API
- Purpose of useRef hook
- The
useRef
hook and how to use it in functional components - Use of
createRef
API in ES6 class components
Thanks for reading this article up to the end. If you notice anything technically inaccurate, you can comment below. If you find this article useful, you can share it on Twitter so that others also benefit from it.
Top comments (6)
What's the difference between useRef() and useRef(null)? I prefer, and could go with the undefined all the time, but online examples always go with the null. So I am wondering.
It is up to you to decide which one of the two to go with. The reason why people go with
null
overundefined
boils down to the difference between the two. You can read about it here.What a detailed and quality guide. Well done!
Hello there. Thanks for the feedback.
This is possibly the best post ever on useRef. I was having a hard time to understand this concept but your explanation was on point. Thanks a lot. Really appreciate.
Thanks. I am glad you found it useful.