{"id":4114,"date":"2024-01-02T21:15:47","date_gmt":"2024-01-02T21:15:47","guid":{"rendered":"https:\/\/www.itersdesktop.com\/?p=4114"},"modified":"2024-01-02T22:46:00","modified_gmt":"2024-01-02T22:46:00","slug":"understanding-react-rendering-part-2-improve-rendering-in-react-apps","status":"publish","type":"post","link":"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/","title":{"rendered":"Understanding React Rendering: Part 2 &#8211; Improve rendering in React apps"},"content":{"rendered":"<p>In the recent post about <a href=\"https:\/\/www.itersdesktop.com\/2024\/01\/02\/understanding-react-rendering-part-1-when-does-react-render-ui-elements\/\">understanding how React renders components<\/a>, we presented how React renders UI elements and also raised awareness of the fact that React renders everything when only one state or prop has been updated. That will get our apps slowly rendered if the components are complicated and take a few milliseconds to complete the rendering. In line with the series of rendering in React, we will discuss some techniques to speed up rendering.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-light-blue ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a5168160c2c0\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a5168160c2c0\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#what-is-shallow-comparison\" >What is shallow comparison?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#using-usememo-hook-to-return-a-memoized-value\" >Using useMemo hook to return a memoized value<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#analysis-of-the-log-messages\" >Analysis of the log messages<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#using-usecallback-hook-to-return-a-memoized-function\" >Using useCallback hook to return a memoized function<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#analysis-of-the-log-messages-2\" >Analysis of the log messages<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#click-on-the-set-text-button\" >Click on the Set Text button<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#click-on-the-button-either-increment-or-click-me\" >Click on the button either Increment or Click me<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#key-takeaways\" >Key Takeaways<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.itersdesktop.com\/vi\/2024\/01\/02\/understanding-react-rendering-part-2-improve-rendering-in-react-apps\/#references\" >References<\/a><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"what-is-shallow-comparison\"><\/span>What is shallow comparison?<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>According to <a href=\"https:\/\/legacy.reactjs.org\/docs\/shallow-compare.html\">React&#8217;s official documentation<\/a>, <code class=\"gatsby-code-text\">shallowCompare<\/code>\u00a0performs a shallow equality check on the current\u00a0<code class=\"gatsby-code-text\">props<\/code>\u00a0and\u00a0<code class=\"gatsby-code-text\">nextProps<\/code>\u00a0objects as well as the current\u00a0<code class=\"gatsby-code-text\">state<\/code>\u00a0and\u00a0<code class=\"gatsby-code-text\">nextState<\/code> objects. It does this by iterating on the keys of the objects being compared and returning true when the values of a key in each object are not strictly equal.<\/p>\n<blockquote>\n<p style=\"padding-left: 40px;\"><code class=\"gatsby-code-text\">shallowCompare<\/code>\u00a0returns\u00a0<code class=\"gatsby-code-text\">true<\/code>\u00a0if the shallow comparison for props or state fails and therefore the component should update.<br \/>\n<code class=\"gatsby-code-text\">shallowCompare<\/code>\u00a0returns\u00a0<code class=\"gatsby-code-text\">false<\/code>\u00a0if the shallow comparison for props and state both pass and therefore the component does not need to update.<\/p>\n<\/blockquote>\n<p>Shallow comparison is a process in React to compare the current state or props of a component to the previous one to determine whether they are dirty or not. React performs a shallow comparison by comparing the reference values of the state or props objects. If the reference values are different, React assumes that the state or props have changed and triggers a re-render. However, if the reference values are the same, React assumes that the state or props have not changed and does not trigger a re-render.<\/p>\n<p>As you have seen in <a href=\"https:\/\/www.itersdesktop.com\/2024\/01\/02\/understanding-react-rendering-part-1-when-does-react-render-ui-elements\/\">part 1 of this series<\/a>, the shallow comparison doesn&#8217;t check the attributes of states, therefore, React performs to render the entire component. In the next section, we will present some tips to improve performance.<\/p>\n<blockquote><p>The\u00a0<code class=\"w3-codespan\">useMemo<\/code>\u00a0and\u00a0<code class=\"w3-codespan\">useCallback<\/code>\u00a0Hooks are similar. The main difference is that\u00a0<code class=\"w3-codespan\">useMemo<\/code>\u00a0returns a memoized value and\u00a0<code class=\"w3-codespan\">useCallback<\/code>\u00a0returns a memoized function.<\/p><\/blockquote>\n<h1><span class=\"ez-toc-section\" id=\"using-usememo-hook-to-return-a-memoized-value\"><\/span>Using <code>useMemo<\/code> hook to return a memoized value<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Getting back to the <a href=\"https:\/\/github.com\/ITersDesktop\/react-caching\">introductory project<\/a> in <a href=\"https:\/\/www.itersdesktop.com\/2024\/01\/02\/understanding-react-rendering-part-1-when-does-react-render-ui-elements\/\">part 1 of this series<\/a>, we will create a new branch from the main one and name it <code>caching<\/code> a branch. We suppose the <code>sum<\/code> function to make an expensive computation so it should not be always called when rendering the <code>SumComp<\/code> component. To avoid that issue, we wrap the logic of the <code>sum<\/code> function into the\u00a0 <code>userMemo<\/code> hook as in the following snippet.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">const sum = useMemo(() =&gt; {\r\n   return expensiveComputing(a, b);\r\n}, [a, b]);<\/pre>\n<p>Then, start the app and load the page on our web browser. Check the screenshot below for your reference.<\/p>\n<figure id=\"attachment_4117\" aria-describedby=\"caption-attachment-4117\" style=\"width: 1104px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-4117 size-full\" title=\"Understanding React Rendering: Part 2 - Using useMemo hook to improve performance\" src=\"https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-example-analysis-01.png\" alt=\"Understanding React Rendering: Part 2 - Using useMemo hook to improve performance\" width=\"1104\" height=\"530\" srcset=\"https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-example-analysis-01.png 1104w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-example-analysis-01-300x144.png 300w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-example-analysis-01-1024x492.png 1024w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-example-analysis-01-768x369.png 768w\" sizes=\"auto, (max-width: 1104px) 100vw, 1104px\" \/><figcaption id=\"caption-attachment-4117\" class=\"wp-caption-text\"><em>Understanding React Rendering: Part 2 &#8211; Using <code>useMemo<\/code> hook to improve performance<\/em><\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"analysis-of-the-log-messages\"><\/span>Analysis of the log messages<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When loading the page fully first, the expensive function is called once. Then,\u00a0we clicked the <code>Click here to change text and color<\/code> twice but the expensive function wasn&#8217;t invoked. React only called and rendered the corresponding elements, e.g., the colour and text of the first paragraph tag. Similarly, when clicking on any of the <code>Increment<\/code> buttons, React also doesn&#8217;t call the function to random colour and text.<\/p>\n<h1><span class=\"ez-toc-section\" id=\"using-usecallback-hook-to-return-a-memoized-function\"><\/span>Using <code>useCallback<\/code> hook to return a memoized function<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>If <code>useMemo<\/code> hook returns a memoized value, <code>useCallback<\/code> hook returns a memoized function. To help you ease the reading flow, let&#8217;s get back to the project as described in the previous section and work out the following example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import React, {useState, useCallback} from 'react';\r\n\r\nfunction ChildComponent({onClick}) {\r\n    console.log('ChildComponent is rendered');\r\n    return (\r\n        &lt;button onClick={onClick}&gt;Click me&lt;\/button&gt;\r\n    );\r\n}\r\n\r\nfunction AnotherSumComp() {\r\n    const [count, setCount] = useState(0);\r\n    const [txt, setTxt] = useState(\"Some text\u2026\");\r\n    const incrementCount = useCallback(() =&gt; {\r\n        console.log(\"Calling an expensive computing...\");\r\n        setCount(prevCount =&gt; prevCount + 1);\r\n    }, [setCount]);\r\n    return (\r\n        &lt;div&gt;\r\n            &lt;p&gt;Text: {txt}&lt;\/p&gt;\r\n            &lt;p&gt;Count: {count}&lt;\/p&gt;\r\n            &lt;button onClick={() =&gt; {\r\n                console.log(\"Setting a new text...\");\r\n                const text = Math.random().toString(36).slice(2, 7);\r\n                setTxt(text);\r\n            }}&gt;Set Text&lt;\/button&gt;\r\n            {\/*&lt;button onClick={() =&gt; { setCount(count + 1); }}&gt;Increment&lt;\/button&gt;*\/}\r\n            &lt;button onClick={() =&gt; { incrementCount(); }}&gt;Increment&lt;\/button&gt;\r\n            &lt;ChildComponent onClick={incrementCount}\/&gt;\r\n        &lt;\/div&gt;\r\n    );\r\n}\r\n\r\nexport default AnotherSumComp;<\/pre>\n<p>In the <code>App<\/code> component, replace <code>&lt;SumComp\/&gt;<\/code> with <code>&lt;AnotherSumComp\/&gt;<\/code>. Start the app and open the console log of your browser. The output will look like in the following screenshot.<\/p>\n<figure id=\"attachment_4122\" aria-describedby=\"caption-attachment-4122\" style=\"width: 910px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-4122 size-full\" title=\"Understanding React Rendering: Part 2 - Using useCallback hook to improve performance\" src=\"https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-01.png\" alt=\"Understanding React Rendering: Part 2 - Using useCallback hook to improve performance\" width=\"910\" height=\"245\" srcset=\"https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-01.png 910w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-01-300x81.png 300w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-01-768x207.png 768w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><figcaption id=\"caption-attachment-4122\" class=\"wp-caption-text\"><em>Understanding React Rendering: Part 2 &#8211; Using <code>useCallback<\/code> hook to improve performance<\/em><\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"analysis-of-the-log-messages-2\"><\/span>Analysis of the log messages<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When the page is fully loaded, only one message is logged because it comes from the child component. The next step is to click on the buttons to see how React renders the components.<\/p>\n<figure id=\"attachment_4123\" aria-describedby=\"caption-attachment-4123\" style=\"width: 821px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-4123 size-full\" title=\"Understanding React Rendering: Part 2 - Using useCallback hook to improve performance\" src=\"https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-03.png\" alt=\"Understanding React Rendering: Part 2 - Using useCallback hook to improve performance\" width=\"821\" height=\"712\" srcset=\"https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-03.png 821w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-03-300x260.png 300w, https:\/\/www.itersdesktop.com\/wp-content\/uploads\/2024\/01\/4114-useCallback-analysis-03-768x666.png 768w\" sizes=\"auto, (max-width: 821px) 100vw, 821px\" \/><figcaption id=\"caption-attachment-4123\" class=\"wp-caption-text\">Understanding React Rendering: Part 2 &#8211; Using <code>useCallback<\/code> hook to improve performance<\/figcaption><\/figure>\n<h3><span class=\"ez-toc-section\" id=\"click-on-the-set-text-button\"><\/span>Click on the <code>Set Text<\/code> button<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Clicking on this button twice, React renders the entire component twice but only the text is updated.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"click-on-the-button-either-increment-or-click-me\"><\/span>Click on the button either <code>Increment<\/code> or <code>Click me<\/code><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Clicking on these buttons, React also renders the entire component but only the child component is updated and the expensive function is called to compute the output.<\/p>\n<h1><span class=\"ez-toc-section\" id=\"key-takeaways\"><\/span>Key Takeaways<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>In this part, we presented how to use <code>useMemo<\/code> and <code>useCallback<\/code> to avoid the issue of rendering everything in React. The <code>useMemo<\/code> hook returns a memorized value while the <code>useCallback<\/code> hook as its name returns a memorized function. For the sake of finality, feel free to clone and work out the source code published at <a href=\"https:\/\/github.com\/ITersDesktop\/react-caching\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/ITersDesktop\/react-caching<\/a> in the <code>caching<\/code> branch.<\/p>\n<h1><span class=\"ez-toc-section\" id=\"references\"><\/span>References<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>[1] React, <a href=\"https:\/\/react.dev\/\" target=\"_blank\" rel=\"noopener\">https:\/\/react.dev\/<\/a>, accessed Jan 2nd 2024<\/p>\n<p>[2] Understanding React Re-rendering: An Overview of Shallow Comparison and Optimization with Examples, <a href=\"https:\/\/www.linkedin.com\/pulse\/understanding-react-re-rendering-overview-shallow-examples-pandey\/\" target=\"_blank\" rel=\"noopener\">https:\/\/www.linkedin.com\/pulse\/understanding-react-re-rendering-overview-shallow-examples-pandey\/<\/a>, accessed Jan 2nd 2024<\/p>\n<p>[3] Optimizing Web Apps in React, <a href=\"https:\/\/www.turing.com\/kb\/optimize-web-apps-in-react\" target=\"_blank\" rel=\"noopener\">https:\/\/www.turing.com\/kb\/optimize-web-apps-in-react<\/a>, accessed Jan 2nd 2024<\/p>\n<p>[4] React <code>useMemo<\/code> Hook, <a href=\"https:\/\/www.w3schools.com\/react\/react_usememo.asp\" target=\"_blank\" rel=\"noopener\">https:\/\/www.w3schools.com\/react\/react_usememo.asp<\/a>, accessed Jan 2nd 2014<\/p>\n<p>[5] React <code>useCallback<\/code> Hook, <a href=\"https:\/\/www.w3schools.com\/react\/react_usecallback.asp\" target=\"_blank\" rel=\"noopener\">https:\/\/www.w3schools.com\/react\/react_usecallback.asp<\/a>, accessed Jan 2nd 2024<\/p>\n<p>[6] Awesome Javascript Interviews, <a href=\"https:\/\/github.com\/rohan-paul\/Awesome-JavaScript-Interviews\/tree\/master\/React\/Hooks\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/rohan-paul\/Awesome-JavaScript-Interviews\/tree\/master\/React\/Hooks<\/a>, accessed Jan 2nd 2024<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the recent post about understanding how React renders components, we presented how React renders UI elements and also raised awareness of the fact that React renders everything when only&hellip; <\/p>\n","protected":false},"author":1,"featured_media":4121,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[827,222],"tags":[836,834,835,837,828,833],"class_list":["post-4114","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react","category-web-programming","tag-improve-performance","tag-optimisation","tag-optimization","tag-performance","tag-react","tag-rendering-components"],"_links":{"self":[{"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/posts\/4114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/comments?post=4114"}],"version-history":[{"count":8,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/posts\/4114\/revisions"}],"predecessor-version":[{"id":4128,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/posts\/4114\/revisions\/4128"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/media\/4121"}],"wp:attachment":[{"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/media?parent=4114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/categories?post=4114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.itersdesktop.com\/vi\/wp-json\/wp\/v2\/tags?post=4114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}