What are refs in React.js and when should you use them?

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

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.

0/10000

No comments so far