Design Converter
Education
Last updated on Feb 27, 2025
•5 mins read
Last updated on Feb 27, 2025
•5 mins read
How do you handle direct DOM manipulation in a React function component?
Working with ref with functional components can feel different if you're used to class components. But React provides simple ways to manage DOM elements without class-based refs.
In this blog, we'll look at different ways to use refs in function components. You'll learn about useRef, ref forwarding, and callback refs. By the end, you'll know when and how to use each method while keeping your app smooth and responsive.
In React, the ref attribute is used to get a reference to a DOM node or a React component instance without triggering a re-render. This is useful when you need to:
• Access DOM nodes directly.
• Handle focus input events dynamically.
• Control media playback (e.g., videos, audio).
• Implement imperative animations.
• Avoid overuse refs while dealing with state management.
Unlike class components, where React.createRef()
is used to create refs, functional components leverage the useRef hook to interact with DOM elements efficiently.
The useRef hook allows you to persist a reference across renders without causing a re-render.
The following Mermaid diagram illustrates how ref interacts with different React components and DOM elements:
Explanation:
• A functional component initializes a ref using useRef(null)
.
• The ref creates a reference object that persists across renders.
• The ref attribute is assigned to a DOM element.
• The ref’s current property allows us to directly access and manipulate the DOM element inside event handlers or effects.
Here’s a simple example of how to use useRef to focus input when a button is clicked:
1import React, { useRef } from "react"; 2 3const InputFocus = () => { 4 const inputRef = useRef(null); // useref null 5 6 const handleClick = () => { 7 if (inputRef.current) { 8 inputRef.current.focus(); // focus input 9 } 10 }; 11 12 return ( 13 <div> 14 <input ref={inputRef} type="text" placeholder="Type something..." /> {/* input element */} 15 <button onClick={handleClick}>Focus Input</button> 16 </div> 17 ); 18}; 19 20export default InputFocus;
Explanation
• We create a useRef hook with null as the initial value (useref null).
• The ref is assigned to the input element via the ref attribute.
• On button click, the current property of the ref is accessed to trigger focus()
.
• This does not cause a re-render, making it efficient.
Callback refs provide a more dynamic way to assign refs and are useful when working with dynamically created DOM nodes.
1import React, { useState } from "react"; 2 3const DynamicInput = () => { 4 const [inputRef, setInputRef] = useState(null); // useref null 5 6 const handleClick = () => { 7 if (inputRef) { 8 inputRef.focus(); // focus input 9 } 10 }; 11 12 return ( 13 <div> 14 <input ref={setInputRef} type="text" placeholder="Dynamic Ref Example" /> 15 <button onClick={handleClick}>Focus Input</button> 16 </div> 17 ); 18}; 19 20export default DynamicInput;
Explanation
• Instead of useRef, we use a state variable to store the ref value.
• The ref attribute is set to a function (setInputRef) which receives the DOM node as its argument.
• This enables us to dynamically manage refs, making it flexible for dynamically generated DOM elements.
Ref forwarding allows a parent component to pass a ref down to a child component, enabling direct interaction with its DOM node.
1import React, { useRef, forwardRef } from "react"; 2 3const Input = forwardRef((props, ref) => { 4 return <input ref={ref} type="text" placeholder="Forwarded Ref Example" />; 5}); 6 7const ParentComponent = () => { 8 const inputRef = useRef(null); // useref null 9 10 const handleClick = () => { 11 if (inputRef.current) { 12 inputRef.current.focus(); // focus input 13 } 14 }; 15 16 return ( 17 <div> 18 <Input ref={inputRef} /> 19 <button onClick={handleClick}>Focus Input</button> 20 </div> 21 ); 22}; 23 24export default ParentComponent;
Explanation
• forwardRef is used to allow the parent component to pass a ref to a child component.
• The ref attribute is assigned to the input element inside the child component.
• The parent component can then call focus()
on the child component’s DOM node.
Refs can be useful in managing focus when handling form validation and error messages.
1const FormComponent = () => { 2 const inputRef = useRef(null); // useref null 3 const [error, setError] = useState(""); 4 5 const handleSubmit = () => { 6 if (!inputRef.current.value) { 7 setError("This field is required!"); // error message 8 inputRef.current.focus(); // manage focus 9 } 10 }; 11 12 return ( 13 <div> 14 <input ref={inputRef} type="text" placeholder="Enter name" /> 15 {error && <p>{error}</p>} 16 <button onClick={handleSubmit}>Submit</button> 17 </div> 18 ); 19};
Refs can also be useful for triggering imperative animations, such as controlling CSS transitions.
1import React, { useRef } from "react"; 2 3const AnimatedBox = () => { 4 const boxRef = useRef(null); 5 6 const animate = () => { 7 if (boxRef.current) { 8 boxRef.current.style.transform = "scale(1.2)"; 9 boxRef.current.style.transition = "transform 0.3s"; 10 } 11 }; 12 13 return ( 14 <div> 15 <div ref={boxRef} style={{ width: 100, height: 100, background: "blue" }} /> 16 <button onClick={animate}>Animate</button> 17 </div> 18 ); 19}; 20 21export default AnimatedBox;
Avoid Overuse: Using refs too frequently (overuse refs) can lead to unreadable code. Prefer state management for UI updates.
Escape Hatch: Refs act as an escape hatch, allowing you to manipulate DOM nodes when state-based reactivity is unnecessary.
Avoid Memory Leaks: Always clean up event listeners attached to refs to avoid memory leaks.
Use Forwarded Ref Wisely: Pass refs only when necessary to avoid unnecessary complexity.
Using ref with functional components helps manage DOM elements, focus inputs, and handle animations. It makes React applications more interactive and responsive.
Stick to state-driven updates when possible. Overusing refs can make code harder to maintain. Use them only when needed for direct DOM interactions.
With the right approach, refs can improve functionality while keeping the code clean and easy to read.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.