In this article, we will dive deep into the use cases of the useRef
hook. I have seen in most of the articles and YouTube videos they only mention the focus
method but in reality, we can achieve a lot more by using useRef
.
In React, useRef
is a hook that provides a way to create a persistent variable that doesn't cause re-renders.
Here are the use cases of useRef
-
Persisting values across renders:
- Unlike state variables, values stored in
useRef
are not tracked by React. - This means changes to
ref.current
will not trigger re-renders to the component.
- Unlike state variables, values stored in
-
Accessing DOM elements:
-
useRef
provides a way to access and manipulate DOM elements directly. - This is useful for tasks like:
- Focusing on input elements.
- Adding event listeners.
- Measuring dimensions.
- Controlling animations.
-
-
Imperative handles:
- You can use
useRef
to store imperative("imperative handles" refer to a way to directly control or interact with external components or libraries that don't necessarily fit neatly within React's declarative paradigm) handles to functions or other objects.
- You can use
Beyond Focus: DOM Operations with useRef in React
While focusing on input elements is a common use case, useRef
offers a versatile toolkit for interacting with the DOM. Here are some other DOM operations you can perform using useRef
:
Now we will create one input component and we will name it RefInput
. Here we are taking an input component you can also try this with any other native or custom component.
import { RefObject } from "react";
export const RefInput = ({
reference,
}: {
reference: RefObject<HTMLInputElement>;
}) => {
return (
<input
type="text"
ref={reference}
/>
);
};
Here, as you can see, we are passing only one prop, which is reference
. In this case, having fewer props available makes it quite challenging to manipulate that component according to your needs.
But With the assistance of useRef
, we can address all of our needs.
1. setting Attributes:-
let's take an example where the user won't be able to pass any input if a few APIs are in a loading state. so for this use case, we have to disable a component so that it won't be able to take any input
import { useEffect, useRef} from "react";
import { RefInput } from "./component";
function App() {
const inputRef = useRef<HTMLInputElement>(null);
// Apis are loading
const isLoading = true;
useEffect(() => {
if (inputRef?.current) {
if (isLoading) {
inputRef.current.setAttribute("disabled", "true");
}
}
}, []);
return (
<>
<RefInput reference={inputRef} />
</>
);
}
export default App;
here we have used the disable
attribute but you can use any other as well according to your requirements
2. Reading Values or setting placeholder
you can read value as well from the input component
const inputValue = inputRef.current.value;
console.log(inputValue);
inputRef.current.placeholder = "Enter here.....";
3. Styling the component
We can also apply appropriate styles or CSS properties to the component. This is the primary challenge whenever we utilize components from third-party sources.
useEffect(() => {
const currentInputRef = inputRef.current;
if (currentInputRef) {
currentInputRef.style.width = "80%";
currentInputRef.style.height = "45px";
currentInputRef.style.borderRadius = "16px";
currentInputRef.style.padding = "10px";
currentInputRef.style.fontFamily = "monospace";
}
}, []);
4. Adding Event listeners
we can add event listeners as well to track the changes in this input box
const [value, setValue] = useState("");
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
useEffect(() => {
const currentInputRef = inputRef.current;
if (currentInputRef) {
// adding onChange event listener to the input element
currentInputRef.addEventListener(
"change",
handleChange as unknown as EventListener
);
}
// removing the event listener
return () => {
if (currentInputRef) {
currentInputRef.removeEventListener(
"change",
handleChange as unknown as EventListener
);
}
};
}, []);
console.log("state===>", value);
5. Measuring Dimensions:
- Getting Width and Height
useEffect(() => {
if (inputRef.current) {
const width = inputRef.current.offsetWidth;
const height = inputRef.current.offsetHeight;
console.log('Width:', width, 'Height:', height);
}
}, []);
6. Scrolling:
-
Scrolling to an Element
const handleClick = () => { if (inputRef.current) { inputRef.current.scrollIntoView({ behavior: 'smooth' }); } };
7. Animations:
-
Triggering CSS Animations
const handleAnimationStart = () => { // ... }; useEffect(() => { if (inputRef.current) { inputRef.current.addEventListener('animationstart', handleAnimationStart); } return () => { if (inputRef.current) { inputRef.current.removeEventListener('animationstart', handleAnimationStart); } }; }, []);
conclusion
Remember, while useRef
provides direct access to the DOM, it's crucial to use it judiciously. For most state-related interactions, React's built-in state management mechanisms (like useState
) are often more suitable.
I hope this expanded explanation clarifies the versatility of useRef
for DOM manipulation in React!
Thank you For Reading This Article 鉂わ笍
Top comments (2)
now useRef is meaningful
Yes, it is a powerful tool. Thank you for reading this article.