{"id":3965,"date":"2020-04-09T07:57:50","date_gmt":"2020-04-09T06:57:50","guid":{"rendered":"https:\/\/sandbox.weareadaptive.com\/?p=3965\/"},"modified":"2020-04-28T07:16:13","modified_gmt":"2020-04-28T06:16:13","slug":"render-performance-optimization-react","status":"publish","type":"post","link":"https:\/\/sandbox.weareadaptive.com\/fr\/2020\/04\/09\/render-performance-optimization-react\/","title":{"rendered":"Render Performance Optimization With React"},"content":{"rendered":"<p style=\"text-align: justify;\">60 frames per second (fps), this number not only represents the refresh rate of a typical pc monitor, but also the time constraint an application must adhere to if it\u2019s to be perceived as being smooth and performant. 60 fps means there are only <em>1 frame\/60 fps<\/em> or 16.66ms for an application to produce a frame and for the browser to take that frame and paint it on the screen. According to <a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/rail\" target=\"_blank\" rel=\"noopener noreferrer\">Google<\/a>, excluding the time needed for the browser to paint the frame leaves only about 10ms. In financial technology, namely in real-time financial applications, not adhering to these rendering constraints would exacerbate performance issues. In these types of applications, constantly streaming prices and market data must be taken to update the components that display the financial instrument\u2019s information, grids that reflect updated positions, and charts that reflect current market movements. Users of these applications expect, perhaps more so than most users of other types of applications, that everything be instantaneously updated.<\/p>\n<p style=\"text-align: justify;\">According to <a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/rail\" target=\"_blank\" rel=\"noopener noreferrer\">Google<\/a> and <a href=\"https:\/\/www.pubnub.com\/blog\/how-fast-is-realtime-human-perception-and-technology\/\" target=\"_blank\" rel=\"noopener noreferrer\">PubNub<\/a>, response times greater than 1 second will cause a user to start losing focus in your application. Greater than 10 seconds would cause users to become frustrated and could even cause them to dismiss your application completely. It is clear that as web applications become larger and more complex, performance is something that needs to be kept under close watch. However, before optimizing, it is important to first understand how the browser works, what affects its performance, and when your application is in need of a performance boost.<\/p>\n<h2>How The Browser Works<\/h2>\n<h2>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4092\" src=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/critical-rendering-path.jpg\" alt=\"\" width=\"1197\" height=\"345\" srcset=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/critical-rendering-path.jpg 1197w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/critical-rendering-path-300x86.jpg 300w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/critical-rendering-path-768x221.jpg 768w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/critical-rendering-path-1024x295.jpg 1024w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/critical-rendering-path-667x192.jpg 667w\" sizes=\"(max-width: 1197px) 100vw, 1197px\" \/><\/h2>\n<p>When you navigate to a webpage, the browser will take the code for that site through something called the critical rendering path. The browser starts by parsing the HTML code to build the DOM tree and the css to build the CSSOM tree. The former represents the hierarchy of HTML elements of the webpage and the latter represents the styles applied to those elements. Together with these steps, the browser must also fetch and execute any javascript code before finalizing the construction of the DOM. The browser will then combine these trees to form the render tree, which represents only the styled nodes that will be rendered on the webpage. This render tree is used during the layout stage, also called reflow, where the browser will calculate the positions, sizes, and geometry of the elements. The final stage is called painting, where the browser uses the information gained from the layout stage to convert each node in the render tree into actual pixels. Continuous reads and writes to the DOM causes the browser to repeatedly go through the layout and paint stages. This is known as layout thrashing, or forced synchronous layout, which can have a huge impact on performance.<\/p>\n<p>&nbsp;<\/p>\n<h2>When to Optimize<\/h2>\n<p style=\"text-align: justify;\">To improve performance you must simply do less work, and the work that you do must be done in less time. In order to achieve this, work can be deferred to a later time to improve loading times, less code can be written so there\u2019s less to process, and heavy computations and objects can be kept in memory to avoid as many unnecessary updates as possible. However, optimization techniques shouldn\u2019t be used prematurely since their effect could be negligible, or even detrimental, and your time could be better spent elsewhere. Performance optimization techniques should be used when it\u2019s certain that a process will have a noticeable impact or after an issue has been noticed and measurements have been taken. In general, it is important to first measure, and then seek to optimize. However, It\u2019s not always necessary to implement performance optimization techniques yourself since frameworks such as React have some optimization techniques already built-in.<\/p>\n<p>&nbsp;<\/p>\n<h2>How React Works<\/h2>\n<p style=\"text-align: justify;\">According to <a href=\"https:\/\/overreacted.io\/react-as-a-ui-runtime\/#host-tree\" target=\"_blank\" rel=\"noopener noreferrer\">Dan Abramov<\/a>, \u201cReact programs usually output <span style=\"color: #27578c;\"><strong>a tree that may change over time<\/strong><\/span>.\u201d He calls that tree a \u201cHost Tree\u201d as it\u2019s outside of react and represents a host environment. The smallest building blocks of these host trees are nodes, or \u201chost instances.\u201d In the browser, the host tree would be the DOM and the host instances would be DOM nodes. React also utilizes renderers, such as React DOM, which act as the bridge between React and the host environment. The smallest building block in React is the React element, which is a javascript object that simply describes a host instance. These objects are immutable, they are tossed away and new ones are created in their place whenever the UI is supposed to change. React elements also form a tree that describes the host tree, and when a render occurs React will update the host tree so that it matches the React tree. The process of determining which host instances need updating is called <a href=\"https:\/\/reactjs.org\/docs\/reconciliation.html\" target=\"_blank\" rel=\"noopener noreferrer\">reconciliation<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h2>React&rsquo;s Built-in Optimization<\/h2>\n<p style=\"text-align: justify;\">Reading and then immediately writing to the DOM forces the browser to reflow. This has a heavier impact on performance than first doing all of the reads to the DOM and then all of the writes because doing each separately allows the browser to defer these actions until the end of the current operation. This is why React uses reconciliation to efficiently determine which elements need to be updated on the DOM and re-rendered, which vastly reduces the number of times the DOM needs to be read from and written to. React also has other optimization techniques such as batching multiple state updates into a single update to prevent multiple re-renders. When using the <strong><span style=\"color: #9e2121;\">useState<\/span><\/strong>() hook, more on hooks later, React will also bail out of a re-render caused by a state change if the new state value is equal, using <strong><span style=\"color: #9e2121;\">Object.is<\/span><\/strong>() for equality check, to the previous state value. This is not the case when using its class component equivalent<strong><span style=\"color: #9e2121;\"> setState<\/span><\/strong>() as every call to it will cause a re-render, unless its new state value comes from a passed function that returned <strong><span style=\"color: #9e2121;\">null<\/span><\/strong>. There are times however, when react\u2019s built-in techniques are not enough, causing us to seek out other tools to improve the performance of our applications.<\/p>\n<p>&nbsp;<\/p>\n<h2>Rendering Optimization<\/h2>\n<p><span style=\"color: #808080;\">shouldComponentUpdate<\/span><\/p>\n<p style=\"text-align: justify;\">React lifecycle methods can help in improving the performance of your application. In particular, the <strong><span style=\"color: #9e2121;\">shouldComponentUpdate<\/span><\/strong>() lifecycle method is called by React prior to calling the component\u2019s render method. Here you may check whether or not a component should be re-rendered. This method only exists for performance optimization and returning <strong><span style=\"color: #9e2121;\">false<\/span><\/strong> will currently not trigger a re-render. However, according to the <a href=\"https:\/\/reactjs.org\/docs\/react-component.html#shouldcomponentupdate\" target=\"_blank\" rel=\"noopener noreferrer\">React docs<\/a>, \u201cin the future React may treat<strong> <span style=\"color: #9e2121;\">shouldComponentUpdate<\/span><\/strong>() as a hint rather than a strict directive, and returning false may still result in a re-rendering of the component.\u201d instead of writing your own <strong><span style=\"color: #9e2121;\">shouldComponentUpdate<\/span><\/strong>() however, it is recommended to have your class component extend <strong><span style=\"color: #9e2121;\">PureComponent<\/span><\/strong>, which implements <strong><span style=\"color: #9e2121;\">shouldComponentUpdate<\/span><\/strong>() and does \u201ca shallow comparison of props and state, and reduces the chance that you\u2019ll skip a necessary update.\u201d<\/p>\n<p><span style=\"color: #808080;\">React.memo<\/span><\/p>\n<p style=\"text-align: justify;\"><strong><span style=\"color: #9e2121;\">React.memo<\/span><\/strong> is a higher order component that takes your component as its first argument and memoizes its props, doing a shallow comparison to determine if the component should re-render. What this means is that if the props passed to your component are referentially equal, React will skip over reconciling that component.<strong><span style=\"color: #9e2121;\"> React.memo<\/span><\/strong> is the functional component equivalent of <strong><span style=\"color: #9e2121;\">PureComponent<\/span><\/strong>, but it differs in that it only considers prop changes. If the shallow comparison is not adequate for your needs, you may also pass a custom comparison function as the second argument. However, using <strong><span style=\"color: #9e2121;\">React.memo<\/span><\/strong> with components that take many props would result in a net loss in performance since you\u2019re simply adding more computations that would most likely still result in a re-render. In most cases, the preferred alternative to using <strong><span style=\"color: #9e2121;\">React.memo<\/span><\/strong> is component composition. Utilizing React\u2019s built in<strong><span style=\"color: #9e2121;\"> children<\/span><\/strong> property, for example, within a component would result in maintaining the referential equality of the child component without the overhead that comes with using <strong><span style=\"color: #9e2121;\">React.memo<\/span>.<\/strong><\/p>\n<p><span style=\"color: #808080;\">useCallback &amp; useMemo<\/span><\/p>\n<p style=\"text-align: justify;\"><strong><span style=\"color: #9e2121;\">useCallback<\/span><\/strong>() and <strong><span style=\"color: #9e2121;\">useMemo<\/span><\/strong>() are React hooks that return memoized functions and values, respectively. Hooks are simply functions that allow function components to utilize state and other React features which, in the past, were only possible with class components. These two hooks are the same,<strong> <span style=\"color: #9e2121;\">useCallback<\/span><\/strong>() is simply a shorthand for using <strong><span style=\"color: #9e2121;\">useMemo<\/span><\/strong>() when it returns a function. They both take a callback function as their first argument and an array of dependencies as their second. When these dependencies change, the passed callback function will run, thus returning an updated value. This happens while the component is rendering, it\u2019s important to keep that in mind so that no side effects occur inside of these hooks since that will cause more re-renders and decrease performance. <strong><span style=\"color: #9e2121;\">useCallback<\/span><\/strong>() should only be used when the returned function needs to retain reference equality, an example being when the function is passed as a prop to an optimized child component. The same applies to <strong><span style=\"color: #9e2121;\">useMemo<\/span><\/strong>(), but <strong><span style=\"color: #9e2121;\">useMemo<\/span><\/strong>() may also be used to avoid an expensive computation on every render. It\u2019s important to note that using<strong> <span style=\"color: #9e2121;\">useCallback<\/span><\/strong>() still requires memory to be allocated for the function definition, not to mention that <strong><span style=\"color: #9e2121;\">useCallback<\/span><\/strong>() would also need to be called. Using this function as an attempt to reduce the number of times a function gets created on every render would actually result in a decrease in performance as more work needs to be done.<\/p>\n<h5 style=\"text-align: justify;\">Example<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-4090 size-full aligncenter\" src=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/optimized-child-component.png\" alt=\"\" width=\"636\" height=\"426\" srcset=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/optimized-child-component.png 636w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/optimized-child-component-300x201.png 300w\" sizes=\"(max-width: 636px) 100vw, 636px\" \/><\/p>\n<p style=\"text-align: justify;\">Let\u2019s say we have an optimized function component, <strong><span style=\"color: #9e2121;\">RenderCounter<\/span><\/strong>, that should only render when its props have changed. All this component does is count the number of times it has been rendered and displays that count on screen. The <strong><span style=\"color: #9e2121;\">Counter<\/span><\/strong> component is passed as an argument to <strong><span style=\"color: #9e2121;\">React.memo<\/span> <\/strong>to achieve the prop memoization. This should mean the component won\u2019t re-render unless its props change, however, that\u2019s not necessarily the case. Notice that on line 13 the prop passed to our <strong><span style=\"color: #9e2121;\">Counter<\/span> <\/strong>component is a function. Since<strong> <span style=\"color: #9e2121;\">React.memo<\/span> <\/strong>does a shallow comparison, it will only check if the reference to the function <strong><span style=\"color: #9e2121;\">onClick<\/span><\/strong> has changed. Now let\u2019s say that this component\u2019s parent looks like this:<\/p>\n<p style=\"text-align: justify;\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4091 size-full\" src=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/non-optimized-component.png\" alt=\"\" width=\"642\" height=\"413\" srcset=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/non-optimized-component.png 642w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/non-optimized-component-300x193.png 300w\" sizes=\"(max-width: 642px) 100vw, 642px\" \/><\/p>\n<p style=\"text-align: justify;\">At first glance you may not notice anything wrong with this component. All it does is force a re-render by updating its state everytime<strong> <span style=\"color: #9e2121;\">onClick<\/span><\/strong> gets executed. The issue is, we don\u2019t necessarily want <strong><span style=\"color: #9e2121;\">RenderCounter<\/span><\/strong> to re-render every time its parent re-renders. Since the<strong> <span style=\"color: #9e2121;\">onClick<\/span><\/strong> function passed to <strong><span style=\"color: #9e2121;\">RenderCounter<\/span><\/strong> gets created on every render, meaning it\u2019s never the same reference, it will always cause <strong><span style=\"color: #9e2121;\">React.memo<\/span> <\/strong>to think that the props have changed, which in turn will always result in a re-render of <strong><span style=\"color: #9e2121;\">RenderCounter<\/span><\/strong>.<\/p>\n<p>To make sure that this does not happen, we can use<strong> <span style=\"color: #9e2121;\">useCallback<\/span><\/strong>() and ensure that the function we pass to <strong><span style=\"color: #9e2121;\">onClick<\/span><\/strong> will retain the same reference and prevent <strong><span style=\"color: #9e2121;\">RenderCounter<\/span><\/strong> from re-rendering unnecessarily.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4089 size-full\" src=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/new-optimized-component.png\" alt=\"\" width=\"721\" height=\"392\" srcset=\"https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/new-optimized-component.png 721w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/new-optimized-component-300x163.png 300w, https:\/\/sandbox.weareadaptive.com\/wp-content\/uploads\/2020\/04\/new-optimized-component-667x363.png 667w\" sizes=\"(max-width: 721px) 100vw, 721px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Closing Remarks<\/p>\n<p style=\"text-align: justify;\">Performance in web applications is more critical than ever as applications grow in size and complexity with each passing moment. This is especially true for real time financial applications where the seemingly chaotic nature of market movements and streamed prices are to be captured and molded into highly responsive and user friendly components. In these applications, every millisecond counts, especially when executing trades and participating in auctions. Such requirements lead us to utilize every performance optimization technique at our disposal. Using frameworks such as React offers inherent performance boosts along with a set of tools that are readily available and can be used to reduce renders and further increase the performance of our applications. However, these tools should be used with caution and only after performance issues have been noticed. Premature optimization could simply lead to more code needing to be unnecessarily executed only to obtain very negligible improvements in performance, or at worst, a decrease in performance. It\u2019s best to measure and attempt to improve performance when issues arise, or if you\u2019re certain a process will have a noticeable impact on your app&rsquo;s performance.<\/p>\n<h2 style=\"text-align: justify;\"><strong>Author:<\/strong><\/h2>\n<h3 style=\"text-align: justify;\"><img loading=\"lazy\" decoding=\"async\" class=\"\" src=\"https:\/\/ca.slack-edge.com\/T04U03PJZ-UK64MKTJ8-1c4f5cd335b2-512\" alt=\"Profile photo for santiago.gomez\" width=\"174\" height=\"174\" \/><\/h3>\n<h2 style=\"text-align: justify;\"><strong>Santiago Gomez<\/strong><\/h2>\n<p style=\"text-align: justify;\">Web Applications Developer, Adaptive Financial Consulting Ltd<\/p>\n<p style=\"text-align: justify;\"><a href=\"mailto:sales@weareadaptive.com\" target=\"_blank\" rel=\"noopener noreferrer\"><span class=\"btn-flat\">Contact us<\/span><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>60 frames per second (fps), this number not only represents the refresh rate of a typical pc monitor, but also &#8230;<\/p>\n","protected":false},"author":24,"featured_media":3980,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,144],"tags":[],"class_list":["post-3965","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-front-end-ui-ux"],"_links":{"self":[{"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/posts\/3965"}],"collection":[{"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/comments?post=3965"}],"version-history":[{"count":0,"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/posts\/3965\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/media\/3980"}],"wp:attachment":[{"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/media?parent=3965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/categories?post=3965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sandbox.weareadaptive.com\/fr\/wp-json\/wp\/v2\/tags?post=3965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}