How to use React `forwardRef` with TypeScript!
Tags: webdev, react, typescript, beginners
Published: 2024-05-10 10:55:43

React's `forwardRef` is a powerful feature that allows you to pass a ref through a component to one of its children. This is particularly useful when you are working with reusable components or when you need to manipulate a DOM element in React. Today, we'll explore how to implement `forwardRef` in React using TypeScript, focusing on a simple example of a text input component. 

## What is `forwardRef`?

Before we dive into the implementation, let's briefly explain what `forwardRef` does. When you use `forwardRef`, you can forward a `ref` to a child component. This means that you can access the underlying DOM node or React component instance of the child component from its parent. This is especially handy when you need to interact with a child component imperatively.

> _"forwardRef lets your component expose a DOM node to parent component with a ref." - react official [docs](https://react.dev/reference/react/forwardRef)_

Remember, in react we do not manipulate DOM directly. But there might be some cases where we need to manipulate DOM e.g. working with react hook forms `Controller` component. In that case, we use `ref` but to work with the child component we implement `forwardRef`. 

> PS: _Every JSX/TSX we write becomes a valid JS object behind the scenes._

There are many ambiguous uses of `forwardRef`I found on the internet while I got errors in my project. Then I found a simple solution which I will share with you in step by step process.

## Step-by-Step Implementation

Let's walk through the process of implementing a text input component for React hook form with `forwardRef` in React using TypeScript.

### 1. Define Props Interface

First, define an interface for the props that the `TextInput` component will accept. In our example, we'll create an interface called `FieldDataProps` with `label`, `value`, and `onChange` properties.

```typescript
interface FieldDataProps {
  value?: string;
  label: string; // input field label
  onChange: (value: string) => void;
}
```

### 2. Create the `TextInput` Component

Next, create the text input component using the `ForwardRefRenderFunction` type from React. This type represents a function component that accepts props and a `ref`. Inside the component, handle the `onChange` event of the input element and invoke the provided `onChange` function with the new value.

```typescript
import React, { ChangeEvent, ForwardRefRenderFunction } from "react";

const TextInput: ForwardRefRenderFunction<HTMLInputElement, FieldDataProps> = (
  { label, onChange, value },
  ref
) => {
  const handleTextInput = (event: ChangeEvent<HTMLInputElement>) => {
    const newValue = event.target.value;
    onChange(newValue);
  };

  return (
    <div className="provide-your-classes"> // using tailwindcss
      <input
        type="text"
        ref={ref}
        value={value}
        onChange={handleTextInput}
        placeholder={" "}
      />
      <label>{label}</label> // label is given dynamically
    </div>
  );
};
```

### 3. Forward the Ref

Now, use `React.forwardRef` to forward the ref to the text input component. Quite simple as it is, just put the whole TSX/JSX function inside `React.forwardRef()` and export. This allows parent components to access the input element's DOM node or React component instance. 

```typescript
const ForwardedTextInput = React.forwardRef(TextInput);
export default ForwardedTextInput;
```

### 4. Usage

You can now use the `TextInput` component in your application. Pass the necessary props and a ref, and you're good to go!

```typescript
// Impleting in react hook form
import TextInput from "./ForwardedTextInput";

// put necessary code here
// following controller component is from React Hook Form
     <Controller
       name="your_input"
       control={control}
       rules={{ required: true }}
       render={({ field: { value, onChange, ref } }) => (
         <TextInput
           ref={ref}
           onChange={onChange}
           value={value}
           label="Your Input"
          />
        )}
      />
```

## Conclusion

Congratulations to us, we've learned how to implement React's `forwardRef` feature with TypeScript by creating a simple text input component. By following these steps, you can create reusable components that accept refs and provide more flexibility in your React applications. 

Got any questions? leave a comment below.

_**WebCraft with Hossain**_!