How to Improve Performance with React forwardRef Smartly

March 22, 2023
copycat
React.js

The Fastest Way to Build React UI

Convert Figma designs to production-ready React.js code. Build stunning apps and landing pages faster than your peers and competitors.

Say Hello to React forwardRef

Think of forwardRef as a secret weapon that allows you to access the ref of a child component from the parent component. It may sound like a minor detail, but it can make a big difference in your development workflow. For instance, let’s say you’re building a custom component that needs to interact with a third-party library, like a date picker or a modal. You need to access that library’s DOM node or component instance to make it work seamlessly with your own component. With forwardRef, this task can be smooth and easy. We’ll explore what React forwardRef is, how it works, and some of its practical use cases. But wait, there’s more! Read on to find out how forwardRef can revolutionize your DOM.

Understanding React forwardRef

https://stackoverflow.com/questions/61984419/react-forwardref-current-is-always-null

React forwardRef is a feature that allows you to pass a ref to a child component from a parent component. It’s often used when accessing the underlying DOM node or component instance of a child component from the parent component. Let’s dive deeper into how forwardRef works and its different use cases.

What does React forwardRef do?

ForwardRef is a higher-order component that takes a component as an argument and returns a new component that passes the ref to the original component. This allows the parent component to access the child component’s ref, which can be used to access the underlying DOM node or component instance.

The syntax for using React.forwardRef is as follows:

1
2
3
const MyComponent = React.forwardRef((props, ref) => {
 
});

In this code, we’re creating a new component called MyComponent that accepts two parameters: props and ref. The props parameter contains any props that are passed to the component, and the ref parameter is a special prop that allows the component to forward its ref to its child component.

Inside the component function, we can use the ref prop just like any other prop. For example, we can pass it to a child component:

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

In this code, we’re returning an input element and passing the ref prop to it. This allows the parent component to access the input’s ref, which can be used to access the input’s DOM node and perform actions like focusing, resizing, or scrolling.

How do you create a forward ref in React?

When you use forwardRef, you pass a function as a ref to the child component, which returns the ref. React takes care of the rest, ensuring that the child component receives the ref and is available to the parent component.

Let’s say you have a custom input component that you want to use in another component. You want to be able to focus the input when the parent component mounts, but you can’t do that directly from the parent component. To solve this, you can use forwardRef to pass the input’s ref to the parent component, which can then use it to focus the input.

First, let’s create our custom input component:

1
2
3
4
5
import React from "react";
 
const CustomInput = React.forwardRef((props, ref) => (
  <input type="text" {...props} ref={ref} />
));

In this code, we’re creating a functional component that takes in any props and a ref. The component simply renders an input element, and we pass the ref to the input element so that the parent component can access it.

Now let’s use our custom input component in a parent component:

1
2
3
4
5
6
7
8
9
10
11
12
13
jsxCopy code
import React, { useRef, useEffect } from "react";
import CustomInput from "./CustomInput";
 
const ParentComponent = () => {
  const inputRef = useRef(null);
 
  useEffect(() => {
    inputRef.current.focus();
  }, []);
 
  return <CustomInput ref={inputRef} />;
};

In this code, we’re creating a functional component that uses our custom input component. We’re using the useRef hook to create a ref for the input, and we’re passing it to our custom input component using the ref prop.

Then, we’re using the useEffect hook to focus the input when the component mounts. We do this by accessing the current property of the inputRef object, which is the actual DOM node, and calling the focus method on it.

And that’s it! With this code, we’re able to use forwardRef to pass the input’s ref from the child component to the parent component, and we’re able to focus the input when the parent component mounts.

You can also learn how to use forwardRef in less than 10 minutes:

What is the use of forward ref?

https://felixgerschau.com/react-forwardref-explained/

ForwardRef can be used in a variety of scenarios, but five common use cases are:

  • accessing the underlying DOM node
  • accessing the component instance
  • creating reusable components
  • integrating with external APIs
  • wrapping third-party libraries

Accessing the underlying DOM node

Sometimes you need to access the underlying DOM node of a child component to do things like set focus, get its size or position, or manipulate it in some other way. To do this, you can use forwardRef to pass the ref to the child component, which can then expose the underlying DOM node to the parent component. Let’s see how to do this with an example:

Let’s say you have a component called MyComponent that renders an input element, and you want to access the input’s DOM node in a parent component. Here’s how you can do it:

  1. Use React.forwardRef to create a higher-order component that accepts a ref prop and forwards it to the child component. Here’s an example: jsxCopy code const MyComponent = React.forwardRef((props, ref) => { return <input type="text" ref={ref} />; });
  2. Render MyComponent in the parent component and pass a ref callback function as the value of the ref prop. This function will be called with the underlying DOM node as its argument when MyComponent mounts. Here’s an example: jsxCopy code function ParentComponent() { const inputRef = React.useRef(null); React.useEffect(() => { console.log(inputRef.current); // logs the input element }, []); return <MyComponent ref={inputRef} />; } In this code, we’re creating a ref using the useRef hook and passing it as the value of the ref prop to MyComponent. We’re also using the useEffect hook to log the inputRef.current value when the component mounts.
  3. When MyComponent mounts, React will call the ref callback function with the underlying DOM node as its argument. In our case, the inputRef.current value will be set to the input element. We can then use this reference to manipulate the input element in the parent component. Note that in order to use React.forwardRef to access the underlying DOM node, the child component must be a DOM element, not a custom component.

Accessing the component instance

Another use case for forwardRef is when you need to access the component instance of a child component from the parent component. This can be useful when triggering a method or changing a state variable on the child component. Using forwardRef, you can pass the ref to the child component and then access its instance methods or state variables from the parent component.

Let’s say you have a component called MyComponent that needs to expose a method called doSomething() to its parent component, and you want to access the instance of MyComponent in the parent component. Here’s how you can do it:

  1. Use React.forwardRef to create a higher-order component that accepts a ref prop and forwards it to the child component. Here’s an example: const MyComponent = React.forwardRef((props, ref) => { const doSomething = () => { console.log('doing something'); }; React.useImperativeHandle(ref, () => ({ doSomething, })); return <div>My Component</div>; }); In this code, we’re defining a function called doSomething() that logs a message to the console. We’re also using the useImperativeHandle hook to expose doSomething() to the parent component via the ref prop.
  2. Render MyComponent in the parent component and create a ref using the useRef hook. Pass this ref as the value of the ref prop to MyComponent. Here’s an example: function ParentComponent() { const myComponentRef = React.useRef(null); const handleClick = () => { myComponentRef.current.doSomething(); }; return ( <div> <button onClick={handleClick}>Do Something</button> <MyComponent ref={myComponentRef} /> </div> ); } In this code, we’re creating a ref using the useRef hook and passing it as the value of the ref prop to MyComponent. We’re also defining a handleClick() function that calls doSomething() on the MyComponent instance via the myComponentRef.current reference.
  3. When MyComponent mounts, React will call the useImperativeHandle callback with the ref as its argument. We’re using this callback to define an object with a single property, doSomething(), which is a reference to the doSomething() function. When the handleClick() function is called, it calls doSomething() on the MyComponent instance via the myComponentRef.current reference. This logs a message to the console.

Creating Reusable Components

Creating reusable components is another great use case for React.forwardRef. By using React.forwardRef, we can create a component that can forward a ref to a child component, enabling the parent component to access the child’s underlying DOM node or component instance. This allows us to create reusable components that can be easily integrated into other React applications, while still maintaining control over the child component.

Here’s an example of how to create a reusable CustomButton component that forwards a ref to its button element:

1
2
3
4
5
6
7
8
9
10
11
12
jsxCopy code
import React, { forwardRef } from "react";
 
const CustomButton = forwardRef((props, ref) => {
  return (
    <button ref={ref} className="custom-button" onClick={props.onClick}>
      {props.children}
    </button>
  );
});
 
export default CustomButton;

In this example, we create a CustomButton component that forwards a ref to its button element using React.forwardRef. We pass the ref to the button element using the ref prop, and we also pass any other props that the parent component may have specified (in this case, onClick and children).

Now, we can use the CustomButton component in other React components, and we can also access the underlying button element if we need to do so. For example, we can use the CustomButton component like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
jsxCopy code
import React, { useRef } from "react";
import CustomButton from "./CustomButton";
 
const App = () => {
  const buttonRef = useRef(null);
 
  const handleClick = () => {
    console.log(buttonRef.current);
  };
 
  return (
    <div>
      <CustomButton ref={buttonRef} onClick={handleClick}>
        Click me!
      </CustomButton>
    </div>
  );
};
 
export default App;

In this example, we create an App component that uses the CustomButton component we created earlier. We also create a buttonRef using the useRef hook, and we pass it to the CustomButton component using the ref prop. Finally, we create a handleClick function that logs the buttonRef to the console when the button is clicked.

By using React.forwardRef to create the CustomButton component, we can access the underlying button element using the buttonRef and do whatever we need to do with it. This allows us to create reusable components that can be easily integrated into other React applications, while still maintaining control over the child component.

Integrating with external APIs

https://blog.miniorange.com/wordpress-custom-external-api-integration/

Many external APIs require direct access to the underlying DOM nodes, which can be challenging to obtain in a React application. By using React.forwardRef, we can easily pass refs to the underlying DOM nodes to external APIs and enable them to manipulate the DOM as needed.

By using React.forwardRef, we can create a layer of abstraction that makes it easier to work with external APIs, while also allowing us to access the underlying DOM node or component instance of the API.

Here’s how to do it:

  1. Importing the forwardRef function from React:
1
import React, { forwardRef } from 'react';
  1. Defining a functional component that takes in a props object and a ref object:
1
2
3
const ExternalApiComponent = forwardRef((props, ref) => {
  ...
});
  1. Defining the initial state of the component:
1
2
3
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
  1. Defining an asynchronous function that fetches data from an external API:
1
2
3
4
5
6
7
8
9
10
11
const fetchData = async () => {
  setLoading(true);
  try {
    const response = await fetch('<https://api.example.com/data>');
    const json = await response.json();
    setData(json);
  } catch (e) {
    setError(e);
  }
  setLoading(false);
};
  1. Rendering the component’s content conditionally based on the component’s state:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (loading) {
  return <div>Loading...</div>;
}
 
if (error) {
  return <div>Error: {error.message}</div>;
}
 
if (!data) {
  return <div>No data available</div>;
}
 
return (
  <div>
    <h1>{data.title}</h1>
    <p>{data.description}</p>
  </div>
);
  1. Exporting the component:
1
export default ExternalApiComponent;

Here’s a real life example of how to integrate with the Google Maps API using React.forwardRef:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import React, { forwardRef, useEffect, useRef } from "react";
 
const GoogleMap = forwardRef((props, ref) => {
  const mapRef = useRef(null);
  const mapInstance = useRef(null);
 
  useEffect(() => {
    if (window.google) {
      mapInstance.current = new window.google.maps.Map(mapRef.current, props.options);
      if (props.onLoad) {
        props.onLoad(mapInstance.current);
      }
    } else {
      const script = document.createElement("script");
      script.src = `https://maps.googleapis.com/maps/api/js?key=${props.apiKey}`;
      script.onload = () => {
        mapInstance.current = new window.google.maps.Map(mapRef.current, props.options);
        if (props.onLoad) {
          props.onLoad(mapInstance.current);
        }
      };
      document.head.appendChild(script);
    }
  }, [props.apiKey, props.onLoad, props.options]);
 
  useEffect(() => {
    if (mapInstance.current && props.onReady) {
      props.onReady(mapInstance.current);
    }
  }, [props.onReady]);
 
  return <div ref={ref} style={{ height: "100%" }} ref={mapRef}></div>;
});
 
export default GoogleMap;

Example explanation

In this example, we create a GoogleMap component that uses React.forwardRef to forward a ref to its div element, allowing the parent component to access the underlying DOM node of the Google Map.

The GoogleMap component also takes a number of props, including apiKey, options, onLoad, and onReady. apiKey is the API key for the Google Maps API, options is an object that specifies the options for the map (such as the zoom level and center point), onLoad is a callback function that is called when the map is loaded, and onReady is a callback function that is called when the map is ready to be used.

Inside the useEffect hook, we check if the Google Maps API has already been loaded. If it has, we create a new instance of the google.maps.Map class and call the onLoad callback function if it was provided. If the Google Maps API has not been loaded, we dynamically load it by creating a new script element and appending it to the document.head. Once the API has been loaded, we create a new instance of the google.maps.Map class and call the onLoad callback function if it was provided.

Finally, we return the div element with the ref prop forwarded to it, and we also pass a style prop to set the height of the element to 100%.

By using React.forwardRef to create the GoogleMap component, we can easily integrate with the Google Maps API and access the underlying DOM node of the map, all while keeping the implementation details of the API hidden from the parent component.

Wrapping Third-Party Libraries

Third-party libraries often have their own APIs and interfaces, and integrating them with a React application can sometimes be challenging. By wrapping third-party libraries with React.forwardRef, we can create a layer of abstraction that makes it easier to use these libraries in a React component, while also allowing us to access the underlying DOM node and/or component instance of the third-party library.

For example, you have a third-party library called FancyButton that you want to use in your React app, but you also want to be able to access the underlying DOM node and/or component instance of FancyButton from your parent component. Here’s how you can do it:

1. Use React.forwardRef to create a higher-order component that accepts a ref prop and forwards it to the FancyButton component. Here’s an example:

1
2
3
4
5
import FancyButton from 'third-party-library';
 
const FancyButtonWrapper = React.forwardRef((props, ref) => {
  return <FancyButton {...props} ref={ref} />;
});

2. Render FancyButtonWrapper in your parent component and create a ref using the useRef hook. Pass this ref as the value of the ref prop to FancyButtonWrapper. Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function ParentComponent() {
  const fancyButtonRef = React.useRef(null);
 
  const handleClick = () => {
    console.log(fancyButtonRef.current);
  };
 
  return (
    <div>
      <button onClick={handleClick}>Log FancyButton DOM Node</button>
      <FancyButtonWrapper ref={fancyButtonRef} />
    </div>
  );
}

In this code, we’re creating a ref using the useRef hook and passing it as the value of the ref prop to FancyButtonWrapper. We’re also defining a handleClick() function that logs the fancyButtonRef.current object to the console.

When FancyButtonWrapper mounts, React will pass the ref to FancyButton, which will attach it to the underlying DOM node of FancyButton. We can then access this DOM node via the fancyButtonRef.current reference. If FancyButton exposes any methods or properties on its instance, we can access them by modifying FancyButtonWrapper to forward them to the parent component using the useImperativeHandle hook. Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
import FancyButton from 'third-party-library';
 
const FancyButtonWrapper = React.forwardRef((props, ref) => {
  const fancyButtonRef = React.useRef(null);
 
  React.useImperativeHandle(ref, () => ({
    getDOMNode: () => fancyButtonRef.current,
    doSomething: () => fancyButtonRef.current.doSomething(),
  }));
 
  return <FancyButton {...props} ref={fancyButtonRef} />;
});

In this code, we’re using the useRef hook to create a new ref called fancyButtonRef that we’re passing to FancyButton. We’re also using the useImperativeHandle hook to expose two methods, getDOMNode() and doSomething(), to the parent component via the ref prop. The getDOMNode() method returns the underlying DOM node of FancyButton, which we can access via the fancyButtonRef.current.

Creating Custom Hooks with React forwardRef

https://daveceddia.com/custom-hooks/

React’s forwardRef can also be used to create custom hooks that can be shared across different components. Custom hooks can be used to abstract away complex logic and make it easier to reuse code across different parts of an application.

What are custom hooks?

Custom hooks are a powerful feature of React that allows developers to extract and reuse functionality across multiple components. A custom hook is a function that uses other hooks or functions to encapsulate a specific behavior or set of behaviors that can be reused throughout an application. In this section, we’ll explore how to create a custom hook with forwardRef and see examples of different use cases for custom hooks with forwardRef.

How do custom hooks work in React?

Custom hooks work similarly to regular hooks, but they can be reused across multiple components. A custom hook is just a normal function that uses hooks inside. The hook logic can be abstracted into the custom hook, making reusing that functionality across your application easier.

Creating a custom hook with forwardRef

To create a custom hook with forwardRef, you need to define a function that takes a ref object as a parameter and returns a callback function that can be passed as the ref prop to a component.

Here’s an example of a custom hook that uses forwardRef to create a reusable form input component:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { forwardRef } from 'react';
 
function useInput() {
  const inputRef = useRef(null);
 
  const focus = () => {
    inputRef.current.focus();
  };
 
  return [inputRef, focus];
}
 
const Input = forwardRef((props, ref) => {
  const [inputRef, focus] = useInput();
 
  return (
    <input {...props} ref={inputRef} />
  );
});
 
export default Input;

In this example, the useInput function is a custom hook that returns an array with two values: the inputRef object and a focus function. The inputRef object can be passed as the ref prop to the Input component, allowing the component to access the underlying DOM node.

Accessing the component’s ref

When using forwardRef with custom hooks, the ref object is passed as a parameter to the custom hook function. The custom hook can then return a callback function that can be passed as the ref prop to a component. This allows the component to access the ref object and use it to interact with the underlying DOM node.

Examples of different use cases for custom hooks with forwardRef

Custom hooks with forwardRef can be used in many different ways, depending on the specific needs of your application. Here are some examples of different use cases for custom hooks with forwardRef:

  • Creating reusable form inputs that can be easily customized and styled
  • Wrapping third-party components to add additional functionality or to make them more accessible
  • Creating custom scroll bars or other custom UI elements that require access to the underlying DOM node
  • Integrating with external APIs or services to provide real-time updates or other dynamic functionality
  • Creating custom hooks that provide common functionality such as authentication, caching, or routing.

Improving Performance with React forwardRef

React forwardRef is useful for component composition and reuse and for improving performance in certain scenarios. This section will explore how forwardRef can help optimize components and prevent unnecessary renders.

How forwardRef can help improve performance

In a React application, rendering is expensive and can slow down the user experience. React provides several performance optimization techniques to mitigate this, such as shouldComponentUpdate and React.memo. Another method is to use forwardRef to optimize components.

Using forwardRef to optimize components

One of the primary benefits of using forwardRef is that it can help optimize components by preventing unnecessary renders. When a parent component re-renders, all child components will re-render by default. However, if a child component is wrapped in forwardRef, it can use React.memo or shouldComponentUpdate to determine if it needs to re-render. This can greatly reduce the number of renders in the application, leading to a smoother user experience.

Preventing unnecessary renders

To prevent unnecessary renders, the child component can implement shouldComponentUpdate or use React.memo to compare its current props with the previous props. If the props haven’t changed, the component can return false from shouldComponentUpdate or React.memo. This will prevent the component from re-rendering, saving valuable resources, and improving performance.

Let’s assume we have a Parent component that renders a Child component. The Child component has a prop data that is passed from the Parent component. The Child component also has a button that triggers an action. Whenever the button is clicked, it causes the Child component to re-render, even if the data prop hasn’t changed. This can be a problem if the data prop is large or if the Child component has other expensive computations that are not necessary.

To prevent this unnecessary re-render, we can use React.forwardRef() to create a wrapper component around the Child component that memoizes the Child component and only re-renders it if the data prop has changed.

Here’s the code example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import React, { forwardRef, memo } from 'react';
 
const Child = ({ data, onClick }) => {
  console.log('Child rendered');
  return (
    <div>
      <p>Data: {data}</p>
      <button onClick={onClick}>Click me</button>
    </div>
  );
};
 
const MemoizedChild = memo(Child);
 
const ChildWrapper = forwardRef(({ data, onClick }, ref) => {
  console.log('ChildWrapper rendered');
  return <MemoizedChild ref={ref} data={data} onClick={onClick} />;
});
 
const Parent = () => {
  const [data, setData] = useState('Hello world');
  const childRef = useRef(null);
 
  const handleClick = () => {
    console.log('Button clicked');
  };
 
  return (
    <div>
      <ChildWrapper ref={childRef} data={data} onClick={handleClick} />
      <button onClick={() => setData('Hello universe')}>Change data</button>
    </div>
  );
};

Here are the steps:

  1. We define the Child component that renders the data prop and a button that triggers the onClick function.
  2. We memoize the Child component using React.memo().
  3. We define a new component called ChildWrapper using React.forwardRef().
  4. We render the memoized Child component inside the ChildWrapper component, passing the data and onClick props and the ref object.
  5. We define the Parent component that renders the ChildWrapper component and a button that changes the data prop.
  6. We use useRef() to create a childRef object that we can use to access the Child component’s methods and properties.
  7. We pass the childRef object and the handleClick function to the ChildWrapper component.
  8. When the button inside the Child component is clicked, it triggers the handleClick function defined in the Parent component.
  9. Whenever the Parent component re-renders, it only re-renders the ChildWrapper component if the data prop has changed, thanks to the memoization of the Child component.

What is difference between useRef and forwardRef?

useRef and forwardRef are two separate features in React that serve different purposes.

useRef is a hook that allows you to create a mutable reference that persists across renders. It returns a plain JavaScript object with a current property that holds the current value of the reference. You can use useRef to store any mutable value, not just DOM nodes.

On the other hand, forwardRef is a higher-order component that allows you to forward a ref from a parent component to one of its children. This is useful when you need to access the underlying DOM node or component instance of a child component from a parent component.

So, while useRef is used to create a mutable reference, forwardRef is used to forward a ref to a child component. They serve different purposes and are used in different situations.

Here is a source on useRef from the official React documentation.

Learn more in 15 minutes about useRef and forwardRef:

Optimizing performance with the help of useRef()

In addition to shouldComponentUpdate and React.memo, the useRef hook can also be used to optimize performance with forwardRef. The useRef hook allows a component to store a mutable value that won’t trigger a re-render. This can be useful for storing references to DOM elements or other expensive resources. By using useRef with forwardRef, the component can access these resources without triggering a re-render.

Let’s say we have a component called MyComponent that renders a list of items. Each item is an object with a unique ID and a name. The component also has a button that lets the user add a new item to the list.

Without optimization, if we add a new item to the list, React will re-render the entire component, even though the existing items haven’t changed. This can become a problem if the list is long and the rendering is expensive.

To optimize the rendering, we can use useRef to keep track of the list items that we have already rendered. Here’s how:

1. Import the useRef hook:

1
import React, { useState, useRef } from "react";

2. In the MyComponent function, declare a ref variable using useRef:

1
2
3
4
5
6
7
function MyComponent() {
  const [items, setItems] = useState([]);
  const newItemNameRef = useRef();
  const renderedItemsRef = useRef([]);
 
  // rest of the component code
}

3. In the component’s render method, use renderedItemsRef.current to render the items that have already been rendered:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function MyComponent() {
  const [items, setItems] = useState([]);
  const newItemNameRef = useRef();
  const renderedItemsRef = useRef([]);
 
  function addItem() {
    const newItemName = newItemNameRef.current.value;
    const newItem = { id: Date.now(), name: newItemName };
    setItems((prevItems) => [...prevItems, newItem]);
    newItemNameRef.current.value = "";
  }
 
  const renderedItems = renderedItemsRef.current;
 
  return (
    <div>
      <input ref={newItemNameRef} />
      <button onClick={addItem}>Add Item</button>
      {items.map((item) => {
        const index = renderedItems.findIndex((ri) => ri.id === item.id);
        if (index > -1) {
          renderedItems.splice(index, 1);
          return <div key={item.id}>{item.name}</div>;
        }
        return null;
      })}
    </div>
  );
}

4. In the useEffect hook that handles the state update, update the renderedItemsRef.current array to include the new items:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function MyComponent() {
  const [items, setItems] = useState([]);
  const newItemNameRef = useRef();
  const renderedItemsRef = useRef([]);
 
  function addItem() {
    const newItemName = newItemNameRef.current.value;
    const newItem = { id: Date.now(), name: newItemName };
    setItems((prevItems) => [...prevItems, newItem]);
    newItemNameRef.current.value = "";
  }
 
  const renderedItems = renderedItemsRef.current;
 
  useEffect(() => {
    renderedItemsRef.current = items.slice();
  }, [items]);
 
  return (
    // rest of the component code
  );
}

With this optimization, when a new item is added to the list, React will only re-render the new item and not the entire list. This can greatly improve the performance of the component, especially for long lists.

Potential downsides of using forwardRef for performance

While using forwardRef for performance can be beneficial, there are also potential downsides to consider.

Potential Downsides of using forwardRefHow to Avoid It
1. Overuse of forwardRef can lead to code complexityUse forwardRef sparingly and only when necessary
2. It can be difficult to debug issues related to ref forwardingKeep track of where the ref is being forwarded and use console logs or debuggers to trace the issue
3. Ref forwarding can add unnecessary overhead if not used properlyOnly use forwardRef for performance-critical components and avoid using it for simple or infrequently rendered components
4. Incorrect use of forwardRef can lead to performance issuesUse forwardRef in the recommended way by passing the ref as the second argument to forwardRef and avoid unnecessary rerenders
5. Ref forwarding can make it harder to reason about component dependenciesCarefully consider the component structure and dependencies before using forwardRef
6. Overuse of forwardRef can lead to poor code maintainabilityUse forwardRef judiciously and document its use clearly
7. Ref forwarding can make it harder to share components across different projectsUse forwardRef in a consistent way across all components and document its use clearly
8. Ref forwarding can make it harder to adopt changes to the React APIUse forwardRef in a future-proof way that is less likely to break with changes to the React API
9. Using forwardRef excessively can make the code harder to read and understandUse forwardRef only when necessary and document its use clearly
10. Ref forwarding can make it harder to write unit tests for componentsWrite tests that cover the use of forwardRef and mock the ref object when necessary

What’s the difference between react forwardRef and React forwardRef Typescript?

The difference between React forwardRef and React forwardRef TypeScript is the way you define the type of the forwardRef.

In regular JavaScript, when you use React.forwardRef, you define the component as a function that takes two arguments: props and ref. The ref argument is passed by the parent component and forwarded to the child component.

In TypeScript, you need to define the type of the forwardRef using a generic type parameter. This generic type parameter defines the type of the ref that is being forwarded. The syntax for defining the type of the forwarded ref in TypeScript is as follows:

1
2
3
const MyComponent = React.forwardRef<RefType, Props>((props, ref) => {
  // Component logic here
});

Here, RefType is the type of the ref that is being forwarded, and Props is the type of the component’s props.

By defining the type of the forwarded ref, you can ensure that the ref is used correctly throughout your component and avoid type errors.

Time to Try forwardRef

React forwardRef is a powerful tool that can significantly improve the functionality and performance of React components. It allows for greater flexibility in accessing underlying DOM nodes and component instances, creating custom hooks, and optimizing performance. However, it is vital to be aware of the potential downsides and take steps to avoid them. Whether you are a seasoned React developer or just starting, learning to use forwardRef effectively can greatly enhance your development experience. So why not try it in your next project and see how it can benefit you? Remember always to keep experimenting and pushing the boundaries of what is possible with React. Happy coding!

Related Articles

  • React.js

    How to Build a Good React Modal

    How to Build a React Modal. A modal(also known as a modal window or lightbox) is a web page element that shows in front of and disables all other page content. The user must interact with the modal either by…

    November 29, 2022
  • React.js

    Ultimate Guide to Fetching Data from API using React Fetch with Clear…

    Introduction to Fetching Data from API Often times, in fullstack web applications, you are required to either interact with a database; this can be a relational or non-relational database, or interact with an API. In such scenarios, you will need to…

    July 20, 2022

Convert Figma To React

Convert Figma designs to production-ready React.js code. Build stunning apps and landing pages faster than your peers and competitors.

Convert Design to Code