useRef can store any mutable data that you want to persist between renders. It helps you to avoid re-rendering of the component when you don't want to.
useRef vs useState
useRef is similar to useState but there are some differences,
- both
useStateanduseRefcan maintain the value between renders. -
useStateis used to store the state of a component whereasuseRefis used to store any mutable value. -
useStatewill cause the component to re-render when the state is updated whereasuseRefwill not cause the component to re-render when the value is updated.
const [text, setText] = useState('')
const handleTextChange = (e) => {
setText(e.target.value)
}
// re-renders the component on every text change
return (
<div>
<input type="text" value={text} onChange={handleTextChange} />
</div>
)
Using useRef to store the value of the input element will not cause the component to re-render when the value is updated.
const textRef = useRef('')
const handleTextChange = (e) => {
textRef.current = e.target.value
}
// no re-renders when the text changes
return (
<div>
<input type="text" value={textRef.current} onChange={handleTextChange} />
</div>
)
useRef is mostly used for,
- storing the previous value of a state or props of a component across rendering of a component
- accessing DOM nodes in React
useRef to store the previous value of a state or props of a component
import React, { useState, useRef } from 'react'
const Slide = ({ selectedSlideIndex }) => {
const [slide, setSlide] = useState(selectedSlideIndex)
const prevSlideRef = useRef()
// update the previous slide value when the slide value changes
useEffect(() => {
prevSlideRef.current = slide
}, [slide])
const prevSlide = prevSlideRef.current
return (
<div>
<p>Current slide: {slide}</p>
<p>Previous slide: {prevSlide}</p>
<button onClick={() => setSlide(slide + 1)}>Next</button>
</div>
)
}
In the above example, useRef helps to maintain the previous value of the slide state variable.
Some of the use cases are,
- undo/redo functionality
- maintaining the previous value of a state variable to compare with the current value and perform some action
- saving a draft if value of a textarea is changed
- showing a confirmation dialog if the value of a textarea is changed and the user tries to navigate away from the page
useRef to access DOM nodes
import React, { useRef, useEffect } from 'react'
const Input = () => {
const inputRef = useRef(null)
// focus the input element when the component is mounted
useEffect(() => {
inputRef.current.focus()
}, [])
return (
<div>
<input ref={inputRef} type="text" />
</div>
)
}
In the above example, useRef helps to access the input element and focus it when the component is mounted.
Some of the use cases are,
- focusing or blurring an element
- accessing the DOM node to get the size of an element
- accessing the DOM node to get the scroll position of an element
Hope this helps to learn the magic of useRef hook. Happy referencing 😃
Top comments (1)
Maybe this is mindblowing to someone:
The benefit: as
latestnever changes (it always has the same object reference) you still do get access to the latest props. This pattern can be easier than writing a bunch ofuseCallback, especially if all of the callbacks can remain stable.Sometimes it can also be useful that the callback changes when props change, but usually when dealing with things like event handlers you just want the latest prop without mutating the rendered callback that is already in DOM.