Skip to content

Commit b41712b

Browse files
Deploy to GitHub pages
0 parents  commit b41712b

File tree

95 files changed

+1783
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+1783
-0
lines changed

.nojekyll

Whitespace-only changes.

404.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png" data-next-head=""/><link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png" data-next-head=""/><link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png" data-next-head=""/><link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png" data-next-head=""/><link rel="icon" type="image/x-icon" href="/images/favicon.ico" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link data-next-font="size-adjust" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/0732dfa8741dc542.css" as="style"/><link rel="stylesheet" href="/_next/static/css/0732dfa8741dc542.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-b66ed8ba6f029a99.js" defer=""></script><script src="/_next/static/chunks/framework-a4ddb9b21624b39b.js" defer=""></script><script src="/_next/static/chunks/main-d4c20200ddabac7f.js" defer=""></script><script src="/_next/static/chunks/pages/_app-31cd0638bbee6098.js" defer=""></script><script src="/_next/static/chunks/pages/_error-fde50cb7f1ab27e0.js" defer=""></script><script src="/_next/static/486XeNk3pwfcC2Uokufu7/_buildManifest.js" defer=""></script><script src="/_next/static/486XeNk3pwfcC2Uokufu7/_ssgManifest.js" defer=""></script></head><body><script async="" defer="" src="https://a.holt.courses/latest.js"></script><div id="__next"><div class="remix-app"><header class="navbar"><h1 class="navbar-brand"><a href="/">Intermediate React v6</a></h1><div class="navbar-info"><a href="https://frontendmasters.com/courses/intermediate-react-v6/" class="cta-btn">Watch on Frontend Masters</a></div></header><div class="content-container"><div class="main"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div></div><noscript><img src="https://a.holt.courses/noscript.gif" alt="" referrerPolicy="no-referrer-when-downgrade"/></noscript><footer class="footer"><ul class="socials"><li class="social"><a href="https://twitter.com/holtbt"><svg fill="none" height="auto" width="32" xmlns="http://www.w3.org/2000/svg" viewBox="0.254 0.25 500 451.95400000000006"><path d="M394.033.25h76.67L303.202 191.693l197.052 260.511h-154.29L225.118 294.205 86.844 452.204H10.127l179.16-204.77L.254.25H158.46l109.234 144.417zm-26.908 406.063h42.483L135.377 43.73h-45.59z" fill="var(--footer-icons)"></path></svg></a></li><li class="social"><a href="https://bsky.app/profile/brianholt.me"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3.268 64 68.414" width="38" height="auto"><path fill="var(--footer-icons)" d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805zm36.254 0C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745z"></path></svg></a></li><li class="social"><a href="https://github.com/btholt"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32"><defs><clipPath id="clip-github-social"><rect width="32" height="32"></rect></clipPath></defs><g id="github-social" clip-path="url(#clip-github-social)"><g id="Group_272" data-name="Group 272" transform="translate(13522.5 -6994)"><path id="Subtraction_33" data-name="Subtraction 33" d="M-24967.5,8041a15.9,15.9,0,0,1-11.312-4.688A15.893,15.893,0,0,1-24983.5,8025a15.893,15.893,0,0,1,4.689-11.315A15.894,15.894,0,0,1-24967.5,8009a15.894,15.894,0,0,1,11.313,4.686A15.893,15.893,0,0,1-24951.5,8025a15.893,15.893,0,0,1-4.689,11.313A15.9,15.9,0,0,1-24967.5,8041Zm-3.781-4.571h0v3.918h7.895v-6.665a1.836,1.836,0,0,0-1.2-1.718c5.1-.617,7.467-2.975,7.467-7.424a7.176,7.176,0,0,0-1.637-4.728,6.74,6.74,0,0,0,.275-1.812,4.34,4.34,0,0,0-.52-2.452.574.574,0,0,0-.359-.1c-1.061,0-3.465,1.411-3.936,1.694a16.644,16.644,0,0,0-4.2-.489,16.379,16.379,0,0,0-3.969.445c-.846-.5-2.91-1.649-3.859-1.649a.566.566,0,0,0-.354.095,4.3,4.3,0,0,0-.521,2.452,6.7,6.7,0,0,0,.244,1.718,7.346,7.346,0,0,0-1.6,4.822,7.263,7.263,0,0,0,1.533,4.985c1.193,1.359,3.115,2.165,5.871,2.464a1.826,1.826,0,0,0-1.129,1.693v.5h0l-.006,0a7.121,7.121,0,0,1-2.033.363,2.608,2.608,0,0,1-.965-.158,4.438,4.438,0,0,1-1.836-1.881,2.361,2.361,0,0,0-1.248-1.091,3.472,3.472,0,0,0-1.217-.3.584.584,0,0,0-.545.224.282.282,0,0,0,.027.367,1.875,1.875,0,0,0,.447.307,4.732,4.732,0,0,1,.561.355,10.726,10.726,0,0,1,1.682,2.755c.043.092.078.163.105.217a3.876,3.876,0,0,0,2.42,1.185,6.036,6.036,0,0,0,.607.025c.875,0,1.988-.124,2-.125Z" transform="translate(11461 -1015)" fill="var(--footer-icons)"></path><g id="Ellipse_670" data-name="Ellipse 670" transform="translate(-13522.5 6994)" fill="none" stroke="var(--footer-icons)" stroke-width="1"><circle cx="16" cy="16" r="16" stroke="none"></circle><circle cx="16" cy="16" r="15.5" fill="none"></circle></g></g></g></svg></a></li><li class="social"><a href="https://linkedin.com/in/btholt"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32"><defs><clipPath id="clip-linkedin-social"><rect width="32" height="32"></rect></clipPath></defs><g id="linkedin-social" clip-path="url(#clip-linkedin-social)"><g id="Group_270" data-name="Group 270" transform="translate(-86.349 -633.073)"><path id="Path_375" data-name="Path 375" d="M115.789,633.073a2.324,2.324,0,0,1,1.682.676,2.194,2.194,0,0,1,.695,1.627V662.8a2.131,2.131,0,0,1-.695,1.609,2.314,2.314,0,0,1-1.646.659H88.69a2.307,2.307,0,0,1-1.646-.659,2.128,2.128,0,0,1-.695-1.609V635.376a2.19,2.19,0,0,1,.695-1.627,2.322,2.322,0,0,1,1.682-.676h27.063Zm-20.224,9.672a2.561,2.561,0,0,0,0-3.584,2.658,2.658,0,0,0-1.938-.712,2.724,2.724,0,0,0-1.957.712,2.371,2.371,0,0,0-.75,1.792,2.4,2.4,0,0,0,.731,1.792,2.605,2.605,0,0,0,1.9.713h.037A2.7,2.7,0,0,0,95.565,642.745ZM96,645.434H91.213V659.88H96Zm17.3,6.144a7.007,7.007,0,0,0-1.573-4.9,5.68,5.68,0,0,0-6.839-.769,5.663,5.663,0,0,0-1.426,1.573v-2.048H98.674q.036.841,0,7.717v6.728h4.791V651.8a3.592,3.592,0,0,1,.146-1.17,2.913,2.913,0,0,1,.878-1.206,2.429,2.429,0,0,1,1.609-.549,2.108,2.108,0,0,1,1.865.914,4.265,4.265,0,0,1,.549,2.341v7.752H113.3Z" fill="var(--footer-icons)"></path></g></g></svg></a></li><li class="social"><div class="terms"><p>Content Licensed Under CC-BY-NC-4.0</p><p>Code Samples and Exercises Licensed Under Apache 2.0</p><p>Site Designed by<!-- --> <a href="https://www.alexdanielson.com/">Alex Danielson</a></p></div></li></ul></footer></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"486XeNk3pwfcC2Uokufu7","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>

CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
intermediate-react-v6.holt.courses

_next/data/486XeNk3pwfcC2Uokufu7/index.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"pageProps":{"post":{"attributes":{"description":"Learn how to optimize React performance using 'useDeferredValue' to manage low priority rendering, a tool that dynamically adapts to user's device speed, in Brian Holt's \"Intermediate React v6\" course by Frontend Masters.","keywords":["React","useDeferredValue","performance optimization","deferred rendering","Brian Holt"]},"html":"<p>So how can we make things less janky?</p>\n<p>In the past we have to use something like <a href=\"https://css-tricks.com/debouncing-throttling-explained-examples/\">throttle or debounce</a> - we&#39;d limit how frequently we&#39;d allow the functions to update. This works but it&#39;s a blunt instrument - it&#39;s complicated code (I have to look up debounce vs throttle every time) and it doesn&#39;t scale with the user&#39;s device. Slow and fast devices alike will get slowed down.</p>\n<p>Enter <code>useDeferredValue</code>. It uses React&#39;s low priority rendering to say &quot;hey, if you&#39;re still busy doing high priority stuff, feel free to delay changing this low priority stuff&quot; to React. What&#39;s cool about that is this <em>will</em> scale with the user&#39;s device. A fast device will chew through updates quickly and get to the low priority updates quickly while a slower device will be given space to sort through high priority updates and wait for the lower ones.</p>\n<p>Let&#39;s make it happen.</p>\n<pre><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">// replace filterStyles</span>\n<span class=\"hljs-keyword\">const</span> deferredBlur = <span class=\"hljs-title function_\">useDeferredValue</span>(blur);\n<span class=\"hljs-keyword\">const</span> deferredBrightness = <span class=\"hljs-title function_\">useDeferredValue</span>(brightness);\n<span class=\"hljs-keyword\">const</span> deferredContrast = <span class=\"hljs-title function_\">useDeferredValue</span>(contrast);\n<span class=\"hljs-keyword\">const</span> deferredSaturate = <span class=\"hljs-title function_\">useDeferredValue</span>(saturate);\n<span class=\"hljs-keyword\">const</span> deferredSepia = <span class=\"hljs-title function_\">useDeferredValue</span>(sepia);\n\n<span class=\"hljs-keyword\">const</span> filterStyle = <span class=\"hljs-string\">`\n blur(<span class=\"hljs-subst\">${deferredBlur}</span>px)\n brightness(<span class=\"hljs-subst\">${deferredBrightness}</span>%)\n contrast(<span class=\"hljs-subst\">${deferredContrast}</span>%)\n saturate(<span class=\"hljs-subst\">${deferredSaturate}</span>%)\n sepia(<span class=\"hljs-subst\">${deferredSepia}</span>%)`</span>;\n\n\n<span class=\"hljs-comment\">// change deferred</span>\n<span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Slider</span>\n <span class=\"hljs-attr\">value</span>=<span class=\"hljs-string\">{blur}</span>\n <span class=\"hljs-attr\">deferred</span>=<span class=\"hljs-string\">{deferredBlur}</span>\n <span class=\"hljs-attr\">onChange</span>=<span class=\"hljs-string\">{(e)</span> =&gt;</span> setBlur(e.target.value)}\n name=&quot;Blur&quot;\n/&gt;</span>\n<span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Slider</span>\n <span class=\"hljs-attr\">value</span>=<span class=\"hljs-string\">{brightness}</span>\n <span class=\"hljs-attr\">deferred</span>=<span class=\"hljs-string\">{deferredBrightness}</span>\n <span class=\"hljs-attr\">onChange</span>=<span class=\"hljs-string\">{(e)</span> =&gt;</span> setBrightness(e.target.value)}\n name=&quot;Brightness&quot;\n/&gt;</span>\n<span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Slider</span>\n <span class=\"hljs-attr\">value</span>=<span class=\"hljs-string\">{contrast}</span>\n <span class=\"hljs-attr\">deferred</span>=<span class=\"hljs-string\">{deferredContrast}</span>\n <span class=\"hljs-attr\">onChange</span>=<span class=\"hljs-string\">{(e)</span> =&gt;</span> setContrast(e.target.value)}\n name=&quot;Contrast&quot;\n/&gt;</span>\n<span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Slider</span>\n <span class=\"hljs-attr\">value</span>=<span class=\"hljs-string\">{saturate}</span>\n <span class=\"hljs-attr\">deferred</span>=<span class=\"hljs-string\">{deferredSaturate}</span>\n <span class=\"hljs-attr\">onChange</span>=<span class=\"hljs-string\">{(e)</span> =&gt;</span> setSaturate(e.target.value)}\n name=&quot;Saturate&quot;\n/&gt;</span>\n<span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Slider</span>\n <span class=\"hljs-attr\">value</span>=<span class=\"hljs-string\">{sepia}</span>\n <span class=\"hljs-attr\">deferred</span>=<span class=\"hljs-string\">{deferredSepia}</span>\n <span class=\"hljs-attr\">onChange</span>=<span class=\"hljs-string\">{(e)</span> =&gt;</span> setSepia(e.target.value)}\n name=&quot;Sepia&quot;\n/&gt;</span>\n</code></pre><ul>\n<li>We still have jank - that&#39;s expected, we have a 200ms delay chucked into our code. But it&#39;s working <em>much</em> better than it was.</li>\n<li>There&#39;s probably a clever way to just useDeferredValue with just the filterStyle or other things - notice it&#39;s deferred <strong>value</strong> and not deferred <strong>state</strong> - you can use it with any value.</li>\n</ul>\n<p>Let&#39;s take it one step further. As long as a deferred value hasn&#39;t changed, that means the filterStyle string hasn&#39;t changed. Using <code>memo</code> like we learned before allows us to prevent the notorious jank-inducer <code>expensiveRender</code> from running. Let&#39;s go do that.</p>\n<p>In DisplayImage</p>\n<pre><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import</span> { memo } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;react&quot;</span>;\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title function_\">memo</span>(<span class=\"hljs-keyword\">function</span> <span class=\"hljs-title function_\">DisplayImage</span>(<span class=\"hljs-params\">{ filterStyle }</span>) {\n <span class=\"hljs-comment\">// other code here</span>\n});\n</code></pre><ul>\n<li>So much less jank</li>\n<li>Now watch that <code>Last render</code> value - notice it doesn&#39;t change until the deferred value catches up</li>\n</ul>\n<p>That&#39;s it! Using our new tools we can even work around heavy computation by using a little help from the React scheduler!</p>\n","markdown":"So how can we make things less janky?\n\nIn the past we have to use something like [throttle or debounce][throttle] - we'd limit how frequently we'd allow the functions to update. This works but it's a blunt instrument - it's complicated code (I have to look up debounce vs throttle every time) and it doesn't scale with the user's device. Slow and fast devices alike will get slowed down.\n\nEnter `useDeferredValue`. It uses React's low priority rendering to say \"hey, if you're still busy doing high priority stuff, feel free to delay changing this low priority stuff\" to React. What's cool about that is this _will_ scale with the user's device. A fast device will chew through updates quickly and get to the low priority updates quickly while a slower device will be given space to sort through high priority updates and wait for the lower ones.\n\nLet's make it happen.\n\n```javascript\n// replace filterStyles\nconst deferredBlur = useDeferredValue(blur);\nconst deferredBrightness = useDeferredValue(brightness);\nconst deferredContrast = useDeferredValue(contrast);\nconst deferredSaturate = useDeferredValue(saturate);\nconst deferredSepia = useDeferredValue(sepia);\n\nconst filterStyle = `\n blur(${deferredBlur}px)\n brightness(${deferredBrightness}%)\n contrast(${deferredContrast}%)\n saturate(${deferredSaturate}%)\n sepia(${deferredSepia}%)`;\n\n\n// change deferred\n<Slider\n value={blur}\n deferred={deferredBlur}\n onChange={(e) => setBlur(e.target.value)}\n name=\"Blur\"\n/>\n<Slider\n value={brightness}\n deferred={deferredBrightness}\n onChange={(e) => setBrightness(e.target.value)}\n name=\"Brightness\"\n/>\n<Slider\n value={contrast}\n deferred={deferredContrast}\n onChange={(e) => setContrast(e.target.value)}\n name=\"Contrast\"\n/>\n<Slider\n value={saturate}\n deferred={deferredSaturate}\n onChange={(e) => setSaturate(e.target.value)}\n name=\"Saturate\"\n/>\n<Slider\n value={sepia}\n deferred={deferredSepia}\n onChange={(e) => setSepia(e.target.value)}\n name=\"Sepia\"\n/>\n```\n\n- We still have jank - that's expected, we have a 200ms delay chucked into our code. But it's working _much_ better than it was.\n- There's probably a clever way to just useDeferredValue with just the filterStyle or other things - notice it's deferred **value** and not deferred **state** - you can use it with any value.\n\nLet's take it one step further. As long as a deferred value hasn't changed, that means the filterStyle string hasn't changed. Using `memo` like we learned before allows us to prevent the notorious jank-inducer `expensiveRender` from running. Let's go do that.\n\nIn DisplayImage\n\n```javascript\nimport { memo } from \"react\";\n\nexport default memo(function DisplayImage({ filterStyle }) {\n // other code here\n});\n```\n\n- So much less jank\n- Now watch that `Last render` value - notice it doesn't change until the deferred value catches up\n\nThat's it! Using our new tools we can even work around heavy computation by using a little help from the React scheduler!\n\n[throttle]: https://css-tricks.com/debouncing-throttling-explained-examples/\n","slug":"making-it-less-janky","title":"Making It Less Janky","section":"Deferred Values","icon":"clock","filePath":"/home/runner/work/intermediate-react-v6/intermediate-react-v6/lessons/08-deferred-values/C-making-it-less-janky.md","nextSlug":"/lessons/wrap-up/congrats","prevSlug":"/lessons/deferred-values/the-project"}},"__N_SSG":true}

_next/data/486XeNk3pwfcC2Uokufu7/lessons/deferred-values/the-project.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)