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
useState
anduseRef
can maintain the value between renders. -
useState
is used to store the state of a component whereasuseRef
is used to store any mutable value. -
useState
will cause the component to re-render when the state is updated whereasuseRef
will 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
latest
never 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.