How to use forwardRef API in React: A Comprehensive Guide with Real-Life Examples

Love Trivedi
ZestGeek
Published in
4 min readAug 26, 2024

--

The forwardRef API in React is a powerful tool that allows components to pass refs through them to their child components. This can be especially useful when you're building reusable components or dealing with third-party libraries. In this article, we’ll delve into the forwardRef API, understand why it’s useful, and look at several real-life examples to illustrate its power.

What is forwardRef?

In React, refs provide a way to access DOM nodes or React elements created in the render method. Normally, you use refs in class components, but with the introduction of hooks, refs can also be used in functional components. forwardRef is a utility function that enables passing a ref from a parent component to one of its children.

Why Use forwardRef?

  1. Ref Forwarding in HOC (Higher-Order Components): HOCs often wrap other components and can obscure the DOM nodes of those components. Using forwardRef, you can pass refs through HOCs to access DOM nodes directly.
  2. Enhanced Component Interoperability: When building libraries or UI kits, providing ref access can be crucial for advanced usage, such as focusing an input field from outside the component.
  3. Managing Focus and Animations: Forwarding refs can be essential in scenarios where focus management and animations are critical, ensuring seamless interaction with the underlying DOM elements.

How Does forwardRef Work?

The forwardRef function takes a React component as its argument and returns a new component. This new component can take a ref prop, which it then forwards to the inner component.

Here’s the basic syntax:

const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="fancy-button">
{props.children}
</button>
));

Real-Life Examples

1. Creating a Custom Input Component

Imagine you want to create a reusable input component that allows the parent component to manage its focus.

import React, { useRef } from 'react';

const CustomInput = React.forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});

function App() {
const inputRef = useRef(null);

const handleFocus = () => {
inputRef.current.focus();
};

return (
<div>
<CustomInput ref={inputRef} placeholder="Type here..." />
<button onClick={handleFocus}>Focus the input</button>
</div>
);
}

export default App;

In this example, clicking the button will programmatically focus the input field, demonstrating the power of ref forwarding in action.

2. Ref Forwarding in Higher-Order Components

Let’s say you have a button wrapped in a Higher-Order Component (HOC). You want to ensure the ref points to the actual button.

import React, { useRef } from 'react';

function withLog(Component) {
class WithLog extends React.Component {
render() {
return <Component {...this.props} />;
}
}

return React.forwardRef((props, ref) => (
<WithLog {...props} forwardedRef={ref} />
));
}

const Button = React.forwardRef((props, ref) => (
<button ref={ref} {...props}>
Click me
</button>
));

const LogButton = withLog(Button);

function App() {
const buttonRef = useRef();

const handleClick = () => {
console.log(buttonRef.current); // Logs the actual button DOM node
};

return (
<div>
<LogButton ref={buttonRef} onClick={handleClick} />
</div>
);
}

export default App;

Here, withLog is a HOC that wraps a component and logs its interactions. By using forwardRef, we ensure that the ref passed to LogButton points to the actual button, not the HOC.

3. Combining forwardRef with Other Hooks

forwardRef can be combined with other hooks to build more sophisticated components. For instance, you might want a component that not only forwards a ref but also uses internal state.

import React, { useRef, useState } from 'react';

const PasswordInput = React.forwardRef((props, ref) => {
const [showPassword, setShowPassword] = useState(false);

return (
<div>
<input
type={showPassword ? 'text' : 'password'}
ref={ref}
{...props}
/>
<button onClick={() => setShowPassword(!showPassword)}>
{showPassword ? 'Hide' : 'Show'}
</button>
</div>
);
});

function App() {
const passwordRef = useRef();

const handleShowPassword = () => {
passwordRef.current.focus();
};

return (
<div>
<PasswordInput ref={passwordRef} />
<button onClick={handleShowPassword}>Focus Password Input</button>
</div>
);
}

export default App;

This example demonstrates a password input field that toggles visibility, while still allowing the parent component to control the focus.

Best Practices with forwardRef

  1. Use Meaningful Ref Names: Name your refs meaningfully, such as inputRef or buttonRef, to make your code more readable and maintainable.
  2. Limit Ref Use: Use refs sparingly. Rely on props and state for most data flows. Use refs for interacting with DOM nodes or when integrating with third-party libraries that require direct DOM access.
  3. Combine with useImperativeHandle: Use the useImperativeHandle hook alongside forwardRef to customize the instance value that is exposed when using refs. This can encapsulate imperative methods like focus or scrollTo.

Conclusion

The forwardRef API in React is a robust feature that can enhance the flexibility and capability of your components. Whether you're building reusable components, integrating with third-party libraries, or managing complex focus scenarios, forwardRef can be a valuable tool. By understanding and utilizing this API, you can build more powerful and maintainable React applications. Happy coding!

--

--

Love Trivedi
ZestGeek

Full Stack Developer | Problem Solver | Knowledge Share, 🚀 Expertise: JavaScript enthusiast specializing in ReactJS, Angular, and Node.js.