What are refs in React.js and when should you use them?
If you’re getting deeper into React and looking to enhance your understanding of its fundamentals, you’re in the right place. Today, we’re diving into an essential, albeit occasionally overlooked feature of React: refs. They offer us an elegant way to directly interact with DOM nodes and React components. But when and why should we use them? Let’s unpack this.
1. Introduction
React is a JavaScript library renowned for building performant and scalable user interfaces. Its genius lies in its virtual DOM and component-based architecture. The virtual DOM ensures efficient updates and rendering, while the component structure makes the code modular and maintainable.
In this vast ecosystem of components and virtual DOM, sometimes there arises a need to bypass this abstraction. That’s where “refs” come into play. They provide a means to directly access the DOM nodes or React components.
2. What are Refs in React?
Refs, short for references, provide a way to access the properties of a DOM node or a React component instance. This is useful because sometimes we need to interact with the underlying DOM API directly.
Unlike the React state or props, refs don’t trigger a re-render when their content changes. They exist outside of the standard React data flow. They allow for a more direct interaction with the virtual DOM, paving a bridge to the actual browser DOM.
2.1 Creating Refs
Refs can be created in multiple ways:
1. React.createRef()
: This method is predominantly used with class components.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef}>Hello, codedamn!</div>;
}
}
2. The useRef
hook: A more modern approach suitable for functional components.
import React, { useRef } from 'react';
function MyFunctionalComponent() {
const myRef = useRef(null);
return <div ref={myRef}>Hello again, codedamn!</div>;
}
2.2 Accessing Refs
Once you’ve created a ref and attached it to an element, you can access it using refName.current
.
For DOM elements:
refName.current
points to the actual DOM node.
const inputRef = useRef(null);
// To focus on the input element
inputRef.current.focus();
For React components:
refName.current
points to the mounted instance of the component.
3. When to Use Refs
Refs are powerful, but they’re not something you’ll need in every component. Overusing refs can make your code imperatively driven, which might compromise the declarative nature of React. However, there are scenarios where they come in handy:
3.1 Direct Manipulation of DOM Elements
Focus management: If you want to set focus on an input field as soon as a modal opens, refs can be instrumental.
const inputRef = useRef(null);
// Somewhere in your logic
inputRef.current.focus();
Integrating third-party libraries: Some libraries might require direct DOM access. Refs facilitate that bridge.
Measurements: Sometimes, you might need to get the dimensions or position of an element, like when creating custom tooltips or popovers.
3.2 Component Instance Access in Class Components
If you’re using class components, refs can be used to:
- Access methods or state of child components: You might have child components with methods that the parent needs to call.
1class ChildComponent extends React.Component {
2 showAlert() {
3 alert('Hello from Child!');
4 }
5
6 render() {
7 // ...
8 }
9}
10
11class ParentComponent extends React.Component {
12 constructor(props) {
13 super(props);
14 this.childRef = React.createRef();
15 }
16
17 handleButtonClick = () => {
18 this.childRef.current.showAlert();
19 }
20
21 render() {
22 return (
23 <>
24 <ChildComponent ref={this.childRef} />
25 <button onClick={this.handleButtonClick}>Trigger Child Alert</button>
26 </>
27 );
28 }
29}
- Trigger animations or other imperative actions: Sometimes, to create fluid UI animations, you might need direct component access.
In conclusion, while the React framework provides fantastic tools to handle state and props in a declarative manner, refs give developers the power to perform imperative tasks when necessary. Always use refs judiciously and remember that the key to mastering React is understanding when and where to use its features effectively.
For more details on refs and their intricacies, you can consult the official React documentation on refs. Happy coding on codedamn!
3.3 Storing Mutable Values without Causing Rerenders
One of the powerful features of useRef
in functional components is its ability to store mutable values without triggering a rerender. React’s reactivity model is built around the state. When state changes, a rerender is triggered to reflect those changes in the UI. However, sometimes, you might want to persist values across renders without actually causing a rerender. This is where useRef
shines.
For instance, consider the scenario where you want to track the number of times a user clicks a button, but you don’t necessarily want to re-render the component with every click:
function ClickCounter() {
const clickCount = useRef(0);
const handleClick = () => {
clickCount.current += 1;
console.log(`Clicked ${clickCount.current} times`);
};
return <button onClick={handleClick}>Click me</button>;
}
In this example, every time the button is clicked, the count is updated, but no rerender is triggered.
3.4 Forwarding Refs
Forwarding refs is a technique in React that allows you to pass a ref
from a parent component directly to a child component’s DOM element. This is especially useful when wrapping components, such as in higher-order components or when dealing with UI libraries.
To forward a ref, you’d use React.forwardRef
:
1const FancyInput = React.forwardRef((props, ref) => (
2 <input ref={ref} className="fancy-input" {...props} />
3));
4
5function ParentComponent() {
6 const inputRef = useRef();
7
8 useEffect(() => {
9 inputRef.current.focus();
10 }, []);
11
12 return <FancyInput ref={inputRef} />;
13}
Use cases and benefits:
- Enhancing components from third-party libraries without losing ref access.
- Creating reusable input components while still having the ability to directly interact with the input’s DOM methods and properties.
4. Common Misuses and Cautions
It’s easy to misuse refs, especially for beginners. One of the primary misuses is over-relying on refs instead of leveraging React’s declarative nature. React is designed around a declarative paradigm, which means you should describe how the UI should look based on the state, not imperatively manipulating the UI.
Potential pitfalls:
- Performance: Direct DOM manipulations can be more costly than letting React handle changes.
- Unexpected behaviors: Manipulating the DOM directly can lead to out-of-sync issues between the React virtual DOM and the actual DOM.
Another common confusion arises between useRef
and useState
. While both can store values, useState
causes rerenders when its value changes, whereas useRef
doesn’t.
5. Alternatives to Refs
Controlled components vs. uncontrolled components: Controlled components have their values controlled by React state, while uncontrolled components use refs for their values.
Leveraging state and props for reactivity: Instead of direct DOM manipulation, it’s often more appropriate to use state and props to cause rerenders and updates.
Context: In situations where you want to avoid prop drilling, the Context API can be a good alternative to provide data to deeply nested components.
6. Best Practices
- Use refs sparingly. Opt for refs only when they are the best or only solution.
- Always lean into the React declarative approach first.
- When using refs to manipulate the DOM directly, always consider accessibility implications.
7. Conclusion
Refs in React are a powerful tool when used judiciously. They offer direct access to DOM elements and provide a way to persist values without causing rerenders. However, it’s crucial to use them in harmony with React’s declarative nature. Remember, just because you can doesn’t mean you should!
8. Additional Resources
- React’s official documentation on refs
- If you’re a visual learner, I’d recommend checking out the various video tutorials available on the codedamn platform which dive deep into the nuances of refs.
Happy coding and keep embracing the React way of thinking!
Sharing is caring
Did you like what Rishabh Rao wrote? Thank them for their work by sharing it on social media.
No comments so far
Curious about this topic? Continue your journey with these coding courses: