React ForwardRef
Tags: react, javascript, webdev, programming
Published: 2023-05-10 15:46:38

## What is Forward Ref

`ForwardRef()` is a utility function in react that let you expose a child components DOM to a parent component with a ref

Usually, the parent component passes the props and data to the child component.

But in some instances like when working with input or where components need to respond with user interactions.

The parent components need direct access to the child components' DOM, to achieve this you can use forward refs

I will explain forward ref in more detail along with examples below

```javascript
const CoolComponent = forwardRef(render);
```

Let us take an example of a form component

**Dead Simple Chat allows you to add chat in your React Applications using powerful** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/javascript-chat-api-sdk)**. With Dead Simple Chat you can add chat to your application in minutes.**

## Create a new project and Exposing a DOM node to the parent component

create a new react js project on your computer and follow along

In your app.js file write the below code

```javascript
import { useRef } from 'react';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
  }

  return (
    <form>
    </form>
  );
}
```

*react*

here we are importing `useRef` and creating a default functional component form

in the form create a const ref and initialize the `useref` with `null`

Now create a new file named `CoolInput.js`

In `CoolInput.js` write the below code there

```javascript
import { forwardRef } from 'react';

const CoolInput = forwardRef(function CoolInput(props, ref) {
  const { label, ..otherProps } = props;
  return (
    <label>
      {label}
      <input {...otherProps} ref={ref} />
    </label>
  );
});

export default MyInput;
```

*CoolInput.js*

here we are importing the `forwardref` from react then we are wrapping the `CoolInput` function in the `forwardref` the `ref` is attached to the input elements ref attribute

Coming back to our `app.js` file add some additional code to it and it should look like this

```javascript
import { useRef } from 'react';
import CoolInput from './input.js';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
  }

  return (
    <form>
      <CoolInput label="Type some text here:" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}
```

*app.js file*

Here we are adding a form and then we are passing the ref to the input.

Additionally we have created a button and attached its `onClick` to a `handleClick` function that focuses the on the text input when it is clicked.

**Dead Simple Chat allows you to add chat in your React Applications using powerful** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/javascript-chat-api-sdk)**. With Dead Simple Chat you can add chat to your application in minutes.**

## Testing the application

Here is what the application looks like

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aynggt1ehsxylufjsb22.png)

when you click on the edit button the input area comes into focus

The form component passes a ref to the `CoolInput`. `CoolInput` component then forwards that ref to the browsers input tag

As a result, the form component can now control the browsers input tag and call input functions on it like focus

## Forwarding refs through multiple components

You can forward the `refs` through multiple components as well. Let us take our example from above and refactor it to pass the `refs` through multiple components

Let us create a file call `middle.js` and there create a component called middle component

In the middle component file paste the below code

```javascript
import React from 'react';
import CoolInput from './input';

const Middle = React.forwardRef(function middle(props, ref) {
  return (
    <div>
      <h2>Middle Component</h2>
      <CoolInput ref={ref} {...props} />
    </div>
  );
});

export default Middle;

```

*Middle.js*

Here we are importing react and importing `CoolInput` then we are wrapping our function middle inside of `forwardref`

Inside of our function middle, we have `CoolInput` and we are passing our ref there to the `CoolInput` Component which in turns passes it to the browser's input

Let us open our `App.js` file and edit it and write the below code there

```javascript
import { useRef } from 'react';
import Middle from './middle';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
  }

  return (
    <form>
      <Middle ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}
```

*app.js*

In the `app.js` we are referencing the Middle component and not the `CoolInput` component and thus we are passing the `ref` from the Form Component to the Middle component to the `CoolInput` Component and from the `CoolInput` Component to the browsers input element

this is how you can pass the `refs` through multiple components

## Exposing an imperative handle instead of a DOM node

Sometimes you do not want to explore the whole DOM node/element to a component you just want to expose some function or API to the component

In our example above we just need the focus function of the browser element in our parent component.

We do not need other functions the input element has like `input. text` etc

We can expose only the needed functions of the DOM element using an imperative handle

Let us learn more about imperative handling using an example

Let us refactor our above example to include just expose focus and scrollInView functions of the input elements instead of the complete element

write the below code in the `input.js` file

```javascript
import { React, forwardRef, useRef, useImperativeHandle } from 'react';

const CoolInput = forwardRef(function CoolInput(props, ref) {
    const inputRef = useRef(null);

    useImperativeHandle(ref, ()=> {
        return {
            focus(){
                inputRef.current.focus()
            },
            scrollIntoView(){
                inputRef.current.scrollIntoView();
            }
        }
    }, []);

    return <input {...props} ref={inputRef} />;

});

export default CoolInput;
```

We are importing `forwardRef`, useRef and `useImperitiveHandle` from react

we are initializing the `useRef` with null and assign it to a `inputRef` `const`

then we are wrapping the `CoolInput` in the `forwardRef` function then we are calling the `useImperitiveHandle` function with the ref as the prop and returning the `focus` and `scrollIntoView` functions

we also return the input ref with the input element

`useImperitiveHandle` is used to customize what value is passed using the ref to the parent component

The empty array is also passed as the third argument so that the custom API is only created once in a component's lifecycle

**Dead Simple Chat allows you to add chat in your React Applications using powerful** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/javascript-chat-api-sdk)**. With Dead Simple Chat you can add chat to your application in minutes.**

## Common Pitfalls

**a. Over-using refs**

You should only use refs for situations where you cannot achieve the desired results using props

If you can use props instead of a ref, you should use the props

using refs increases app complexities

**b. slowdown in performance**

using refs causes increased re-rendering of the components and slows down the application hence they should only be used when necessary

**c. Incompatibility with older versions of react**

the refs are incompatible with older versions of react and hence cannot be used in older applications

**d. maintenance of code and readability of code**

refs cause readability and maintenance problems because they stretch to multiple files and you need to follow the tread and trace where this is leading

**e.  Should not be used in higher-order components**

Higher order components should not use refs because it increases complexity and may cause hard-to-debug errors

refs should only be used in lower order components such as an input tag or a scroll view and should be designed to achieve a specific objective

**Dead Simple Chat allows you to add chat in your React Applications using powerful** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/javascript-chat-api-sdk)**. With Dead Simple Chat you can add chat to your application in minutes.**

## Forward Refs using Examples

Here are a few more examples of using refs

`WriteText.js` file

```javascript
import React from 'react';

const WriteText = React.forwardRef((props, ref) => {
  return <input ref={ref} type="text" {...props} />;
});

export default WriteText;
```

`App.js`

```javascript
import React, { useRef } from 'react';
import WriteText from './WriteText';

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

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

  return (
    <div>
      <WriteText ref={inputRef} />
      <button onClick={handleButtonClick}>Elements in focus is Input</button>
    </div>
  );
}

export default App;
```

Here the `WriteText` components forward the input element directly to the parent

**Dead Simple Chat allows you to add chat in your React Applications using powerful** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/javascript-chat-api-sdk)**. With Dead Simple Chat you can add chat to your application in minutes.**

## Example 2: forwarding refs to an instance of a child component

Here we are going to expose a method of the child component to the parent component

The parent component can then call the function inside of the child component

```javascript

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

const Calculator = React.forwardRef((props, ref) => {
  const [count, setCount] = useState(0);

  useImperativeHandle(ref, () => ({
    add: () => {
      setCount(count => count + 1);
    }
  }));

  return <div>Number: {count}</div>;
});

export default Calculator;
```

*Calculator.js*

This is the `calculator.js` the child component file.

next, we look at the `App.js` file

```javascript
import React, { useRef } from 'react';
import Calculator from './Calculator';

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

  const handleButtonClick = () => {
    CalculatorRef.current.add();
  };

  return (
    <div>
      <Calculator ref={CalculatorRef} />
      <button onClick={handleButtonClick}>Add number</button>
    </div>
  );
}

export default App;
```

*app.js*

In the `app.js` we can cal the Calculator ref function `Add()` to add the number to the count.

Thus in this way, we can access the child components method from the parent component

## ForwardRef Reference

**forwardRef(render)**: You can call `forwardRef(render)` to let your component receive a ref and forward it to a child component

**Parameters**

`render` the render function for your component. The react calls this render function with props and refs that the component received from its parent

The JSX will be returning from your component. A component received from `forwardRef` can also receive a ref prop

**Return**

`forwardRef` Returns a component that you can render in JSX

**Caveats**

In strict mode, the react will call the render function twice. But if your render function is pure as it should be this should not affect the output of your component.

## Conclusion

In this article, we have learned what are react refs, and how to use them.

This article was originally written on the DeadSimpleChat article: [React ForwardRef](https://deadsimplechat.com/blog/react-forwardref/)

I hope you liked the article

Thanks for reading