React Performance Optimization Techniques Part 1

Anas Mustafa - Sep 28 - - Dev Community

React is a powerful library for building user interfaces, known for its extensive ecosystem, large community, and flexibility in building complex and dynamic applications. One of its core features is the Virtual DOM, which helps React efficiently manage UI updates.

The Virtual DOM is an in-memory representation of the real DOM. When the state of a component changes, React compares the current Virtual DOM with a previous snapshot to detect differences. This allows React to only update the parts of the real DOM that have changed, improving performance. However, in larger applications with complex component trees, frequent re-renders can become computationally expensive, as React must recreate and compare the Virtual DOM each time a state change occurs.

To mitigate the performance cost of unnecessary re-renders, React provides several optimization techniques that allow developers to improve the efficiency of their applications.

There are several techniques to improve React performance, and below is a list of those that are effective and can be applied to any application:

  1. list virtualization
  2. lazy loading images
  3. memoization
  4. throttling events
  5. debouncing events
  6. code splitting
  7. React fragments
  8. useTransition hook
  9. web workers

In this article, I will focus on the first three techniques: list virtualization, lazy loading images, and memoization. In my next article, I will explore the remaining topics, except for web workers, as I have already written a detailed article on that subject, which you can find here: Web Workers.

Now, let's dive into how these techniques can enhance performance, starting with list virtualization.

1. list virtualization

list virtualization time taken
Rendering a large list is expensive, not only during the initial load time, as React has to render the entire list before displaying the UI. This is where list virtualization comes into play.

Consider this: why load the entire list at once if the user can only see a small portion of it due to screen size? Instead of rendering the entire list, we can render only the visible portion and load more items as the user scrolls. This is exactly what list virtualization does—only rendering the items that are currently in view, significantly improving performance for large lists.
this feature is used by most of social media apps like facebook, x and instegram.

list virtualization time taken

In the image above, you can see how X (formerly Twitter) effectively renders an infinite number of posts by only displaying a fixed number at a time. This is achieved through list virtualization.

To implement list virtualization in React, we can use one of two libraries: react-window or react-virtualized, both created by the same author. In this case, we will use react-window due to its simplicity.

I will demonstrate how to implement it using react-window and also show the difference with a regular map implementation.

  1. install the library ```shell

Yarn

yarn add react-window

NPM

npm install --save react-window

2. In this example, we use the `AutoSizer` component to ensure the list takes up all available space:
```typescript


import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
import "./styles.css";

export const Window_List = () => {
const Row = ({ index, style }: { index: any; style: any }) => (
<div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
Row {index} 
</div>
);
return (
<AutoSizer>
{({ height, width }: { height: any; width: any }) => (
<List
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
>
{Row}
</List>
)}
</AutoSizer>
)};


Enter fullscreen mode Exit fullscreen mode


list time taken

You can see that the load time is not significantly affected when using list virtualization, which is expected since only the visible items are loaded initially.

  1. here a list without virtualization ```ts

export const List = ({ count }: { count: number }) => {
return (

    { new Array(count).fill(null).map((_, index) => { return ( <> {index % 2 ? (
  • Row {index}
  • ) : (
  • Row {index}
  • )} > ); } )}

);
};




![list virtualization time taken](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wybps53fbb7mdq7ymgzu.png)

>You can see that the load time is significantly longer when dealing with a normal list, which increases exponentially as the number of items grows.

> **Important:** Use list virtualization only when handling large lists. While it minimizes loading time, the application still needs to update the screen with new data as the user scrolls, which means rendering additional components.

## 2. lazy loading images

Lazy loading is a technique used to defer the loading of off-screen images until the user scrolls near them. This helps improve the initial page load time by only loading the necessary resources upfront, and deferring others until they are needed. This can greatly enhance the performance and user experience of your application, especially when dealing with media-heavy pages.

In React, lazy loading can be implemented efficiently using the native `loading="lazy"` attribute for images, or by using more advanced techniques like Intersection Observer for customized control over when and how images load.

#### Why Use Lazy Loading?

- **Improved performance**: Lazy loading images can significantly reduce the initial page load time, especially on pages with many images. Only images that are visible in the viewport are loaded immediately, reducing the number of requests and the amount of data loaded initially.
- **Better user experience**: Faster initial load times lead to a smoother and more responsive experience for users, particularly on slower networks or less powerful devices.
- **Bandwidth savings**: Lazy loading helps save bandwidth by only loading images that the user actually scrolls to, preventing unnecessary data usage.
#### Without Lazy Image: 

When images are not lazily loaded, they are all fetched as soon as the page loads, even if they are off-screen and not immediately visible to the user. This can significantly increase the initial page load time and affect performance, especially if your page contains many images or large media files.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/217mjpwxwc5p5xtz9de6.gif)

>In the above example, all images are being loaded upfront, causing delays in rendering the entire page.

---
#### Basic Example: Lazy Loading with `loading="lazy"`

The simplest way to implement lazy loading in React is by using the `loading="lazy"` attribute on the `<img>` tag. This attribute tells the browser to defer loading the image until it's needed.

Image description

In this example, the browser will automatically lazy load the images as the user scrolls down, without requiring any additional JavaScript.


Advanced Example: Lazy Loading with Intersection Observer

For more control over the lazy loading behavior, you can use the Intersection Observer API. This API allows you to observe when an element enters or exits the viewport, and can be used to lazy load images only when they are about to be displayed on the screen.

Image description
In this example, the LazyImage component uses the Intersection Observer API to detect when the image enters the viewport. When the image is about to be visible, it loads the image source (src). Otherwise, it displays a placeholder, optimizing both performance and user experience.

Conclusion

Lazy loading images can greatly improve both performance and user experience by deferring the loading of off-screen images until they're needed. Whether using the native loading="lazy" attribute or a more advanced custom solution with Intersection Observer, lazy loading is a simple yet powerful optimization technique for modern web applications.

3. memoization

Memoization is a powerful optimization technique, and the name comes from "memo," which refers to saving something for later use. In React, memoization helps by caching the results of computations or function calls so that they are not repeated unnecessarily. This improves the overall performance of your application by avoiding redundant re-renders and recalculations.

>In React, memoization can be achieved in three main ways, each offering unique capabilities:

  1. useMemo
  2. memo
  3. useCallback

1. useMemo

The useMemo hook allows you to cache the result of a function call, making it available for later use without recalculating.
When you call a function for the first time, useMemo executes it normally. However, on subsequent calls with the same dependencies (input values), it simply returns the cached value, thus saving computation time.

>This is particularly useful when the function is computationally expensive, as it prevents the costly operation from being executed on every render unless necessary.

> u can find full code here

here u can find code for normal function call



const [a, seta] = useState("");
const [b, setb] = useState("");

function do_something(a: string, b: string) {
    console.log("do_something called");
    return a + b;
}
return (
&lt;button
    onClick={() =&gt; {
        console.log(do_something(a, b));
    }}
    className="button"&gt;
    Click Me
&lt;/button&gt;
);
}


</code></pre></div>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2vc9j22mwh3vedg3qzt.gif" alt="any description"></p>

<p>In the previous example, the <code>"do_something called"</code> message is printed every time the button is clicked, even though the parameters <code>a</code> and <code>b</code> haven't changed. This shows that the function <code>do_something</code> is recalculated on every render, which is not ideal when working with <strong>expensive computations</strong>.</p>

<p>By using the <code>useMemo</code> hook, we can <strong>memoize</strong> the result of the function call and ensure that <code>do_something</code> only runs when <code>a</code> or <code>b</code> changes, rather than on every click.</p>

<p>Here's how <code>useMemo</code> solves this problem:</p>
<div class="highlight"><pre class="highlight typescript"><code>

<span class="kd">const</span> <span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">seta</span><span class="p">]</span> <span class="o">=</span> <span class="nf">useState</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>
<span class="kd">const</span> <span class="p">[</span><span class="nx">b</span><span class="p">,</span> <span class="nx">setb</span><span class="p">]</span> <span class="o">=</span> <span class="nf">useState</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>

<span class="kd">function</span> <span class="nf">do_something</span><span class="p">(</span><span class="nx">a</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">b</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">do_something called</span><span class="dl">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">a</span> <span class="o">+</span> <span class="nx">b</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">memo_do_something</span> <span class="o">=</span> <span class="nf">useMemo</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nf">do_something</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">),</span> <span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">]);</span>
<span class="k">return </span><span class="p">(</span>
<span class="o">&lt;</span><span class="nx">button</span>
    <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">memo_do_something</span><span class="p">);</span>
    <span class="p">}}</span>
    <span class="nx">className</span><span class="o">=</span><span class="dl">"</span><span class="s2">button</span><span class="dl">"</span><span class="o">&gt;</span>
    <span class="nx">Click</span> <span class="nx">Me</span>
<span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span><span class="p">);</span>
<span class="p">}</span>


</code></pre></div>
<p>In this updated code:</p>

<ul>
<li>The function <code>do_something</code> is now <strong>memoized</strong> using the <code>useMemo</code> hook.</li>
<li>
<p>The <code>"do_something called"</code> log is only printed when the values of <code>a</code> or <code>b</code> change. On subsequent clicks, the memoized value is reused, avoiding the need to recalculate the result.<br>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwgdggehi94xw0agbdys.gif" alt="any description"></p>

<ul>
<li>you would notice that the <code>"do_something called"</code> is not printed when u click the button as it uses the cashed value, it instead printed when the states in the dependency array change <code>[a,b]</code>.
##### Key Takeaways:</li>
</ul>
</li>
<li><p><code>useMemo</code> helps to prevent unnecessary recalculations by <strong>memoizing</strong> the result of expensive functions.</p></li>
<li><p>It will only recompute when one of the values in the dependency array (<code>[a, b]</code>) changes, making it ideal for performance optimization in large applications.</p></li>
</ul>

<hr>
<h4>
  <a name="2-memo" href="#2-memo">
  </a>
  2. Memo
</h4>

<p><code>React.memo</code> is a higher-order component (HOC) used to memoize functional components. It ensures that a component only re-renders if its props change. </p>

<blockquote>
<p>This is particularly useful for components that receive the same props frequently but don't need to re-render.</p>
</blockquote>

<p>lets build a small example to show how <code>React.memo</code> can be useful <br>
down here u can see the virtual dom structure of the project</p>

<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phvsqa3xae1bnq6s06bd.png" alt="any description">4</p>

<p>In this example, we have an <code>App</code> component that renders two child components: <code>Child_1</code> and <code>Child_2</code>. Inside <code>Child_1</code>, there is another nested component, <code>Child_1_1</code>. Each of these components receives a prop (<code>prop</code>), and we trigger a re-render by updating the state (<code>variable</code>) through a button click.</p>

<hr>
<h5>
  <a name="behavior-without-raw-reactmemo-endraw-" href="#behavior-without-raw-reactmemo-endraw-">
  </a>
  Behavior without <code>React.memo</code>:
</h5>

<ol>
<li>Every time the <code>variable</code> is incremented in <code>App</code>, all child components (<code>Child_1</code>, <code>Child_2</code>, and <code>Child_1_1</code>) are re-rendered, even though their props do not change.</li>
<li>This is unnecessary and can degrade performance in larger applications since React re-renders components even when they receive the same props.</li>
</ol>

<blockquote>
<p>u can find full code <a href="https://gist.github.com/anasmustafa123/3bfdf3d6d265afaa4b292d96f0284a17">here</a></p>
</blockquote>
<div class="highlight"><pre class="highlight typescript"><code>

<span class="kd">function</span> <span class="nf">App</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">App rerender</span><span class="dl">'</span><span class="p">);</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">variable</span><span class="p">,</span> <span class="nx">setVariable</span><span class="p">]</span> <span class="o">=</span> <span class="nf">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="k">return </span><span class="p">(</span>
    <span class="o">&lt;&gt;</span>
        <span class="o">&lt;</span><span class="nx">button</span>
            <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="p">{</span>
                <span class="nf">setVariable</span><span class="p">((</span><span class="nx">old</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">old</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span><span class="o">&gt;</span>  
            <span class="nx">increment</span>
        <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="nx">Child_1</span> <span class="nx">prop</span><span class="o">=</span><span class="p">{</span><span class="mi">555</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="nx">Child_2</span> <span class="nx">prop</span><span class="o">=</span><span class="p">{</span><span class="mi">555</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">Child_1</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">prop</span> <span class="p">}:</span> <span class="p">{</span> <span class="nl">prop</span><span class="p">:</span> <span class="kr">any</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`child_1 rendered`</span><span class="p">);</span>
    <span class="k">return </span><span class="p">(</span>
        <span class="o">&lt;</span><span class="nx">div</span>
            <span class="o">&lt;</span><span class="nx">Child_1_1</span> <span class="nx">prop</span><span class="o">=</span><span class="p">{</span><span class="mi">555</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">};</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">Child_2</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">prop</span> <span class="p">}:</span> <span class="p">{</span> <span class="nl">prop</span><span class="p">:</span> <span class="kr">any</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`child_2 rendered`</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;&lt;</span><span class="sr">/div&gt;</span><span class="err">;
</span><span class="p">};</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">Child_1_1</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">prop</span> <span class="p">}:</span> <span class="p">{</span> <span class="nl">prop</span><span class="p">:</span> <span class="kr">any</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`child_1_1 rendered`</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;&lt;</span><span class="sr">/div&gt;</span><span class="err">;
</span><span class="p">};</span>


</code></pre></div>
<blockquote>
<p>In the GIF, every time the button is clicked, <strong>all components rerender</strong>, even though the <code>prop</code> values of <code>Child_1</code>, <code>Child_2</code>, and <code>Child_1_1</code> haven't changed. This results in unnecessary renders.</p>
</blockquote>

<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mk9s3jyjpvmru4thxs0x.gif" alt="any description"></p>

<hr>
<h5>
  <a name="introducing-raw-reactmemo-endraw-" href="#introducing-raw-reactmemo-endraw-">
  </a>
  Introducing <code>React.memo</code>:
</h5>

<p>To prevent unnecessary re-renders, we can wrap these child components with <code>React.memo</code>. This ensures that they only re-render when their props change, reducing the overall rendering load.</p>
<div class="highlight"><pre class="highlight typescript"><code>

<span class="k">export</span> <span class="kd">const</span> <span class="nx">Child_1</span> <span class="o">=</span> <span class="nf">memo</span><span class="p">(({</span> <span class="nx">prop</span> <span class="p">}:</span> <span class="p">{</span> <span class="nl">prop</span><span class="p">:</span> <span class="kr">any</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`child_1 rendered`</span><span class="p">);</span>
    <span class="k">return </span><span class="p">(</span>
        <span class="o">&lt;</span><span class="nx">div</span>
            <span class="o">&lt;</span><span class="nx">Child_1_1</span> <span class="nx">prop</span><span class="o">=</span><span class="p">{</span><span class="mi">555</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">});</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">Child_2</span> <span class="o">=</span> <span class="nf">memo</span><span class="p">(({</span> <span class="nx">prop</span> <span class="p">}:</span> <span class="p">{</span> <span class="nl">prop</span><span class="p">:</span> <span class="kr">any</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`child_2 rendered`</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;&lt;</span><span class="sr">/div&gt;</span><span class="err">;
</span><span class="p">});</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">Child_1_1</span> <span class="o">=</span> <span class="nf">memo</span><span class="p">(({</span> <span class="nx">prop</span> <span class="p">}:</span> <span class="p">{</span> <span class="nl">prop</span><span class="p">:</span> <span class="kr">any</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`child_1_1 rendered`</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;&lt;</span><span class="sr">/div&gt;</span><span class="err">;
</span><span class="p">});</span>


</code></pre></div>
<blockquote>
<p>In the GIF after introducing <code>React.memo</code>, when you click the button, only the <code>App</code> component re-renders. Neither <code>Child_1</code>, <code>Child_2</code>, nor <code>Child_1_1</code> re-renders since their props remain unchanged. </p>
</blockquote>

<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/41m2dio5nd020zdcylx3.gif" alt="any description"></p>
<h5>
  <a name="conclusion" href="#conclusion">
  </a>
  <strong>Conclusion</strong>:
</h5>

<p>By using <code>React.memo</code>, you prevent unnecessary re-renders of child components when their props remain the same. This technique is particularly beneficial in applications with complex component hierarchies or expensive re-renders, as it helps optimize performance by avoiding redundant renders. However, it's important to note that <code>React.memo</code> should only be used when needed, as overusing it can sometimes introduce complexity without much benefit.</p>

<hr>
<h4>
  <a name="3-usecallback" href="#3-usecallback">
  </a>
  3. useCallback
</h4>

<p>The <code>useCallback</code> hook allows you to <strong>cache the function definition</strong> itself, which means React will not recreate the function on every render unless the specified dependencies change.</p>
<h4>
  <a name="why-is-this-useful" href="#why-is-this-useful">
  </a>
  Why is this useful?
</h4>

<ul>
<li><p><strong>Function recreation on every render</strong>: In React, functions inside components are redefined each time the component re-renders. This means even though the function's logic hasn’t changed, React will treat it as a new function. If you pass such a function as a prop to child components, React will think the prop has changed and unnecessarily re-render those child components.</p></li>
<li><p><strong>Prevent unnecessary child component re-renders</strong>: By caching the function definition with <code>useCallback</code>, React ensures that the function reference remains the same until its dependencies (usually state or props) change. This prevents child components from being re-rendered unnecessarily.</p></li>
</ul>
<h5>
  <a name="example-using-raw-usecallback-endraw-to-prevent-unnecessary-rerenders" href="#example-using-raw-usecallback-endraw-to-prevent-unnecessary-rerenders">
  </a>
  Example: Using <code>useCallback</code> to Prevent Unnecessary Re-renders
</h5>

<p>In the previous example, let's modify the <code>Child_1</code> component to accept a function as a prop, which will help us demonstrate the <code>useCallback</code> hook.</p>
<h5>
  <a name="before-using-raw-usecallback-endraw-" href="#before-using-raw-usecallback-endraw-">
  </a>
  Before Using <code>useCallback</code>
</h5>
<div class="highlight"><pre class="highlight typescript"><code>

<span class="kd">function</span> <span class="nf">App</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">App rerender</span><span class="dl">'</span><span class="p">);</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">variable</span><span class="p">,</span> <span class="nx">setVariable</span><span class="p">]</span> <span class="o">=</span> <span class="nf">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="kd">function</span> <span class="nf">do_something</span> <span class="p">()</span> <span class="p">{</span>
        <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">do_something is called</span><span class="dl">'</span><span class="p">);</span>
        <span class="k">return</span> <span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return </span><span class="p">(</span>
        <span class="o">&lt;&gt;</span>
            <span class="o">&lt;</span><span class="nx">button</span>
                <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="p">{</span>
                <span class="nf">setVariable</span><span class="p">((</span><span class="nx">old</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">old</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
                <span class="p">}}</span><span class="o">&gt;</span>
                <span class="nx">increment</span>
            <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">Child_1</span> <span class="nx">prop</span><span class="o">=</span><span class="p">{</span><span class="nx">do_something</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">}</span>
<span class="k">export</span> <span class="k">default</span> <span class="nx">App</span><span class="p">;</span>


</code></pre></div>
<blockquote>
<p>In this example, <code>Child_1</code> re-renders every time <code>App</code> re-renders, even though the function <code>do_something</code> hasn't changed. This happens because <code>do_something</code> is redefined on every render of <code>App</code>, causing React to think the prop passed to <code>Child_1</code> has changed.</p>
</blockquote>

<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0idbglc96hsfvmqcyggi.gif" alt="any description"></p>

<hr>
<h5>
  <a name="solution-using-raw-usecallback-endraw-" href="#solution-using-raw-usecallback-endraw-">
  </a>
  Solution: Using <code>useCallback</code>
</h5>

<p>By using the <code>useCallback</code> hook, we can cache the <code>do_something</code> function to avoid its recreation on each render, thus preventing <code>Child_1</code> from re-rendering unnecessarily.</p>
<div class="highlight"><pre class="highlight typescript"><code>

<span class="c1">// change do_something to</span>
<span class="kd">const</span> <span class="nx">cashed_do_something</span> <span class="o">=</span> <span class="nf">useCallback</span><span class="p">(</span><span class="kd">function</span> <span class="nf">do_something</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">do_something is called</span><span class="dl">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">hello world</span><span class="dl">"</span><span class="p">;</span>
<span class="p">},</span> <span class="p">[]);</span>
<span class="c1">// update prop</span>
<span class="o">&lt;</span><span class="nx">Child_1</span> <span class="nx">prop</span><span class="o">=</span><span class="p">{</span><span class="nx">cashed_do_something</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>

</code></pre></div>
<blockquote>
<p>With <code>useCallback</code>, React will cache the <code>cashed_do_something</code> function, and <code>Child_1</code> will only re-render when the dependencies of <code>useCallback</code> (in this case, none) change. This optimizes the rendering process, reducing unnecessary renders of <code>Child_1</code>.</p>
</blockquote>

<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8loz8n92r1p6kj31py1h.gif" alt="any description"></p>
<h5>
  <a name="conclusion" href="#conclusion">
  </a>
  Conclusion
</h5>

<p>Using <code>useCallback</code> is an effective way to avoid unnecessary re-renders caused by passing newly created function references to child components. This hook is particularly beneficial in applications where performance is a concern, especially when dealing with deeply nested component trees or passing functions as props frequently.</p>
Enter fullscreen mode Exit fullscreen mode
Enter fullscreen mode Exit fullscreen mode
. . . . .
Terabox Video Player