<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 🈚️うひょ🤪</title>
    <description>The latest articles on DEV Community by 🈚️うひょ🤪 (@uhyo_).</description>
    <link>https://dev.to/uhyo_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F296676%2Fa2824025-30b8-4e15-9286-e843c616e1ad.jpg</url>
      <title>DEV Community: 🈚️うひょ🤪</title>
      <link>https://dev.to/uhyo_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uhyo_"/>
    <language>en</language>
    <item>
      <title>TypeScript 4.5 Shortens Path to Safer Standard Library</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Sat, 02 Oct 2021 02:08:39 +0000</pubDate>
      <link>https://dev.to/uhyo_/typescript-4-5-shortens-path-to-safer-standard-library-256m</link>
      <guid>https://dev.to/uhyo_/typescript-4-5-shortens-path-to-safer-standard-library-256m</guid>
      <description>&lt;p&gt;Amongst the new features of &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/"&gt;TypeScript 4.5&lt;/a&gt;, support for &lt;a href="https://github.com/microsoft/TypeScript/pull/45771"&gt;loading external packages in place of built-in type definitions (standard library)&lt;/a&gt; is particularly of note. The original intent seems to be externalizing &lt;code&gt;lib.dom.d.ts&lt;/code&gt; as &lt;a href="https://github.com/microsoft/TypeScript/issues/44795"&gt;@types/web&lt;/a&gt; so that users can have separate upgrading schedule for TypeScript's core type definitions and one for DOM. The type definitions for DOM are fragile and often breaks backwards compatibility, probably because they are auto-generated.&lt;/p&gt;

&lt;p&gt;Thanks to this nicely generalized solution for externalized standard library, &lt;a href="https://github.com/uhyo/better-typescript-lib"&gt;better-typescript-lib&lt;/a&gt;, a library developed by the author, also receives huge benefit. Particularly, installation is far easier starting from better-typescript-lib v2 that supports TS 4.5 and later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is better-typescript-lib?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/uhyo/better-typescript-lib"&gt;better-typescript-lib&lt;/a&gt; is a package that provides alternative type definitions for standard library.&lt;/p&gt;

&lt;p&gt;TypeScript's built-in type definitions are sometimes problematic in view of safety. For example, the return type of &lt;code&gt;JSON.parse&lt;/code&gt; is any 😱 and it is too easy to guide users to the unsafe hell.&lt;/p&gt;

&lt;p&gt;As TypeScript needs to keep backwards compatibility, directly fixing built-in type definitions is impossible. Previous solutions for this kind of problems have been compiler options, but something like &lt;code&gt;--strictStandardLibrary&lt;/code&gt; does not look like a right way to go.&lt;/p&gt;

&lt;p&gt;better-typescript-lib solves the problem by replacing the entire built-in type definitions with safer ones. It ships with alternative complete set of type definitions for supported ECMAScript and DOM features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Previous Installation Steps of better-typescript-lib
&lt;/h2&gt;

&lt;p&gt;Before TS 4.5, installation of better-typescript-lib was a complicated task. Three steps were required:&lt;/p&gt;

&lt;p&gt;1​. Install &lt;code&gt;better-typescript-lib&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; better-typescript-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2​. Add &lt;code&gt;"noLib": true&lt;/code&gt; to tsconfig.json so that TypeScript's built-in type definitions are not automatically loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  "lib": ["es5", "dom"]
&lt;/span&gt;&lt;span class="gi"&gt;+  "noLib": true
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3​. Manually load needed libs from inside better-typescript-lib.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;reference path="./node_modules/better-typescript-lib/lib.es5.d.ts" /&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;reference path="./node_modules/better-typescript-lib/lib.dom.d.ts" /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  New Installation Step
&lt;/h2&gt;

&lt;p&gt;Thanks to TS 4.5's new feature, now you can use the safer type definitions by literally one step:&lt;/p&gt;

&lt;p&gt;1​. Install &lt;code&gt;better-typescript-lib&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; better-typescript-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done! Wow, everything is so automatic. Now TypeScript loads safer type definitions instead of built-in ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the New Installation Step Works
&lt;/h2&gt;

&lt;p&gt;Starting from TS 4.5, TypeScript detects packages of name with form &lt;code&gt;@typescript/lib-[lib]&lt;/code&gt; and loads that package in place of corresponding built-in type definition. For example, &lt;code&gt;@typescript/lib-es2015&lt;/code&gt; replaces built-in &lt;code&gt;lib.es2015.d.ts&lt;/code&gt;. What a simple but widely applicable solution!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@typescript&lt;/code&gt; scope is owned by TypeScript team, of course, but package managers support installing packages with different names. better-typescript-lib utilizes this feature and have below dependency definitions in package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/dom@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2015"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2015@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2016"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2016@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2017"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2017@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2018"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2018@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2019"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2019@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2020"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2020@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es2021"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es2021@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-es5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/es5@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-esnext"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/esnext@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/header@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-scripthost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/scripthost@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/lib-webworker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@better-typescript-lib/webworker@2.0.0-alpha.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, safer type definitions published as &lt;code&gt;@better-typescript-lib/[lib]&lt;/code&gt; are installed with names &lt;code&gt;@typescript/lib-[lib]&lt;/code&gt; so that they are used instead of built-in type definitions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this depends on the behavior of package managers that flattens contents in &lt;code&gt;node_modules&lt;/code&gt;. Package managers with different strategy for dependency management may not work well. Support for such environments may be added in the future if there are several requests.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;TypeScript 4.5's new feature for replacing built-in type definitions shall have wide application. better-typescript-lib is one of the earliest users of the new feature and is now able to provide safety with far easier installation step.&lt;/p&gt;

&lt;p&gt;You can try now by installing TypeScript 4.5 Beta and &lt;code&gt;better-typescript-lib@2.0.0-beta&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>Is HTML A Programming Language? — A Definitive Answer</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Tue, 27 Apr 2021 01:44:25 +0000</pubDate>
      <link>https://dev.to/uhyo_/is-html-a-programming-language-a-definitive-answer-4c7e</link>
      <guid>https://dev.to/uhyo_/is-html-a-programming-language-a-definitive-answer-4c7e</guid>
      <description>&lt;p&gt;Hello. I created &lt;strong&gt;the HTML programming language (THPL)&lt;/strong&gt;, a programming language whose source code is an HTML document. Therefore, HTML is a programming language!&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="https://github.com/uhyo/the-html-programming-language/blob/master/docs/tutorial.md"&gt;THPL Tutorial&lt;/a&gt; to learn more about THPL.&lt;/p&gt;

&lt;p&gt;Here are a couple of examples.&lt;/p&gt;

&lt;p&gt;Hello World in HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My First HTML Program&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/the-html-programming-language@0.1.0/browser.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;output&amp;gt;&lt;/span&gt;Hello, world!&lt;span class="nt"&gt;&amp;lt;/output&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even FizzBuzz in HTML is possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;FizzBuzz&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/the-html-programming-language@0.1.0/browser.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"fizzbuzz"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;dl&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;rem3&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;abbr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;math&amp;gt;&amp;lt;rem&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;3
          &lt;span class="nt"&gt;&amp;lt;/abbr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;rem5&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;abbr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;math&amp;gt;&amp;lt;rem&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;5
          &lt;span class="nt"&gt;&amp;lt;/abbr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;text&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;abbr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;math&amp;gt;&amp;lt;eq&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;var&amp;gt;&lt;/span&gt;rem3&lt;span class="nt"&gt;&amp;lt;/var&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;meter&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/meter&amp;gt;&amp;lt;/abbr&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;gt;&amp;lt;abbr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;math&amp;gt;&amp;lt;eq&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;var&amp;gt;&lt;/span&gt;rem5&lt;span class="nt"&gt;&amp;lt;/var&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;meter&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/meter&amp;gt;&amp;lt;/abbr&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;gt;&amp;lt;ruby&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;00&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rt&amp;gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;/rt&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;10&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rt&amp;gt;&lt;/span&gt;Fizz&lt;span class="nt"&gt;&amp;lt;/rt&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;01&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rt&amp;gt;&lt;/span&gt;Buzz&lt;span class="nt"&gt;&amp;lt;/rt&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;11&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rt&amp;gt;&lt;/span&gt;FizzBuzz&lt;span class="nt"&gt;&amp;lt;/rt&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/ruby&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/dl&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;output&amp;gt;&amp;lt;var&amp;gt;&lt;/span&gt;text&lt;span class="nt"&gt;&amp;lt;/var&amp;gt;&amp;lt;wbr&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/output&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ruby&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;meter&amp;gt;&lt;/span&gt;100&lt;span class="nt"&gt;&amp;lt;/meter&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;rt&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/rt&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;rt&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;gt;&amp;lt;abbr&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"fizzbuzz"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;abbr&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;gt;&amp;lt;math&amp;gt;&amp;lt;plus&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/abbr&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/abbr&amp;gt;&amp;lt;/rt&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ruby&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;abbr&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"fizzbuzz"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;meter&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/meter&amp;gt;&amp;lt;/abbr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it's obvious that you can write programs in HTML!&lt;/p&gt;

&lt;h2&gt;
  
  
  Q&amp;amp;As
&lt;/h2&gt;

&lt;p&gt;I have gathered feedback from a Japanese community. Here are feedbacks and answers to them in a form of Q&amp;amp;As.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: But a &lt;code&gt;script&lt;/code&gt; tag exists in your source code, so the HTML document itself is not a program.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: the &lt;code&gt;script&lt;/code&gt; tag exists only for automatically executing the HTML program when opened with a browser, so this is not essential for HTML to be a programming language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: you need a JavaScript interpreter to run an HTML program. This means that HTML is not a standalone programming language.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Yeah. Then Ruby is not a programming language because it is run by a C interpreter, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: But HTML identifies itself as a markup language, not programming language.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: You should already know that name is no more than historical stuff. Please complain that JavaScript is calling itself Java first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What you created is only that THPL interpreter thing, so HTML is not affected at all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: The THPL interpreter is just an auxiliary tool that helps understanding THPL. Defining syntax and semantics is essential for something to be a programming language. Syntax already exists for HTML, and I defined semantics directly onto HTML, so HTML is now a programming language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: HTML is a language for defining document data in the form of tree structure, not a program. HTML is more like JSON, YAML or S-expression, which are still not programming languages.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: This point is worth discussing, but please remember that programs are finally interpreted as &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;abstract syntax trees&lt;/a&gt;. In this sense, code for normal programming languages can also be seen as one that defines data in the form of tree structure. With this in mind, difference between HTML and other programming languages are quite vague.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: But program ASTs are different from other data formats in that they don't have other uses. HTML is originally for document markups, and JSON and YAML are for general purpose data exchange.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Okay, please wait for my next project which uses JavaScript programs as general-purpose data format. Then you would say JavaScript is not a programming language.&lt;/p&gt;




&lt;p&gt;Now what do you think? Is HTML a programming language? Discuss!&lt;/p&gt;

</description>
      <category>html</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Use Resource Bundles Now -- A Static Web Server</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Sun, 14 Mar 2021 15:32:28 +0000</pubDate>
      <link>https://dev.to/uhyo_/use-resource-bundles-now-a-static-web-server-214o</link>
      <guid>https://dev.to/uhyo_/use-resource-bundles-now-a-static-web-server-214o</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/WICG/resource-bundles"&gt;Resource Bundles&lt;/a&gt; is a new proposal regarding the problem of nested resource loading on the web. HTTP/2 Server Push previously tried to solve the problem without success; Resource Bundles is the next iteration of the attempt to push the web to the era of native ES Modules.&lt;/p&gt;

&lt;p&gt;In the Resource Bundles era, bundlers like webpack would emit a Resource Bundle instead of a big JavaScript file. Browsers would natively understand Resource Bundles.&lt;/p&gt;

&lt;p&gt;A resource bundle is simply a set of multiple resources. A resource is a pair of raw payload and all HTTP headers for that payload, identified by URLs. In addition to a resource bundle, bundlers would also emit a “manifest”, a dependency graph between resources in the resource bundle. Thanks to this, browsers can download all the resources needed by one request.&lt;/p&gt;

&lt;p&gt;By browsers natively understanding Resource Bundles, efficient caching of resources is enabled too. Browsers can choose to request a subset of whole resource bundle, only requesting ones that aren't cached yet. The server that serves resource bundles would also support subsetting.&lt;/p&gt;

&lt;p&gt;Although Resource Bundles are in its very early stage and few of its details are decided, you can try using Resource Bundles now. The author created a tools for parsing and serializing Resource Bundles based on the current draft of the proposal, as well as a CLI for inspecting and creating Resource Bundles and a static server for serving resources from a Resource Bundle.&lt;/p&gt;

&lt;p&gt;The last one, static server, is actually going aside from the main purpose of Resource Bundles, and is described as “&lt;a href="https://github.com/WICG/resource-bundles/blob/main/other-uses.md"&gt;other uses&lt;/a&gt;” in the proposal. As resource bundles already include HTTP headers for each resource, configuring a static web server would be made extremely easy with Resource Bundles. This means that, in a future, bundler config would include HTTP headers for generated resources.&lt;/p&gt;

&lt;p&gt;Finally, you can try that static server now! Try &lt;a href="https://github.com/uhyo/resourcebundles/tree/master/packages/static-server"&gt;@resourcebundles/static-server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: this work is totally unofficial.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>resourcebundles</category>
    </item>
    <item>
      <title>What If Every Color Is Given Its Own Name? Here It Is!</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Fri, 26 Feb 2021 08:39:39 +0000</pubDate>
      <link>https://dev.to/uhyo_/what-if-every-color-is-given-its-own-name-here-it-is-blg</link>
      <guid>https://dev.to/uhyo_/what-if-every-color-is-given-its-own-name-here-it-is-blg</guid>
      <description>&lt;p&gt;What is the most comprehensive way of expressing colors in CSS? For a majority of developers, it should be color names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* &amp;lt;- color name for #0000ff */&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, color names have one critical downside; not all colors are given names. While the sRGB color space can express 16,777,216 colors, only less than 0.002% of them are given names by the CSS standard.&lt;/p&gt;

&lt;p&gt;That's why the author has created &lt;a href="https://everycolor.vercel.app/"&gt;Everycolor&lt;/a&gt;. With this package, all colors are given systematic names. It comes with a PostCSS plugin that converts the Everycolor names to the &lt;code&gt;#123456&lt;/code&gt; notation, so you can use the Everycolor names in your CSS now!&lt;/p&gt;

&lt;p&gt;Let's see what the Everycolor names look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;redhalfwhite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* #ff8080 */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everycolor gives the name &lt;code&gt;redhalfwhite&lt;/code&gt; to &lt;code&gt;#ff8080&lt;/code&gt;, as this color is halfway towards white (&lt;code&gt;#ffffff&lt;/code&gt;) from red (&lt;code&gt;#ff0000&lt;/code&gt;). Wow, how easy it is!&lt;/p&gt;

&lt;p&gt;Then, can you guess what name &lt;code&gt;#ff4040&lt;/code&gt; is? Yes, it's &lt;code&gt;redquarterwhite&lt;/code&gt;. Now you know how to express colors you want to use!&lt;/p&gt;

&lt;p&gt;With Everycolor, you can express every single color with names rather than hard-to-recognize numbers.&lt;/p&gt;

&lt;p&gt;We also provide a website where you can convert color codes to Everycolor names. This is very useful for learning Everycolor quickly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://everycolor.vercel.app/"&gt;https://everycolor.vercel.app/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, let's see a little more complicated examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* #14211a */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;quarterimperceptiblegreensomewhatlittleslighttealsomewhatbitgray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* #c7eaf9 */&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;navyhalfquartersomewhatlittleimperceptiblebluetealhalfquarterlittleslightaquahalfquarterslightimperceptibleinfinitesimalwhite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* #e4d923 */&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;maroonhalfquarterbitredolivehalfsomewhatlittleimperceptibleyellowsomewhatimperceptibleinfinitesimalwhite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow, so understandable! 😍&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>What If You Don't Have to Remember Tailwind CSS Classes? Here It Is!</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Sat, 30 Jan 2021 16:27:09 +0000</pubDate>
      <link>https://dev.to/uhyo_/what-if-you-don-t-have-to-remember-tailwind-css-classes-here-it-is-1495</link>
      <guid>https://dev.to/uhyo_/what-if-you-don-t-have-to-remember-tailwind-css-classes-here-it-is-1495</guid>
      <description>&lt;p&gt;&lt;em&gt;This article is an English translation of an article: &lt;a href="https://zenn.dev/uhyo/articles/lightwindcss"&gt;Tailwind CSSからクラス名覚えにくさを消したらどうなる？　こうなった&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/uhyo/articles/lightwindcss"&gt;Tailwind CSS&lt;/a&gt; is a CSS framework with which you utilize predefined CSS classes to compose a design.&lt;/p&gt;

&lt;p&gt;I created a new library, &lt;strong&gt;Lightwind CSS&lt;/strong&gt;, which inherits all the goodness of Tailwind CSS but does not require you to memorize class names specific to Tailwind CSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/uhyo/lightwindcss"&gt;https://github.com/uhyo/lightwindcss&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros and Cons of Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;An example from &lt;a href="https://tailwindcss.com/"&gt;the official site of Tailwind CSS&lt;/a&gt; is quoted below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;figure&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"md:flex bg-gray-100 rounded-xl p-8 md:p-0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These classes correspond to plain CSS as follows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;md:flex&lt;/code&gt; → &lt;code&gt;@media (min-width: 768px) { display: flex; }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bg-gray-100&lt;/code&gt; → &lt;code&gt;background-color: #F3F4F6;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rounded-xl&lt;/code&gt; → &lt;code&gt;border-radius: 0.75rem;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p-8&lt;/code&gt; → &lt;code&gt;padding: 2rem;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;md:p-0&lt;/code&gt; → &lt;code&gt;@media (min-width: 768px) { padding: 0; }&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, &lt;code&gt;display: flex&lt;/code&gt; is shortened into &lt;code&gt;flex&lt;/code&gt;. Also, &lt;code&gt;pedding&lt;/code&gt; is abbreviated as &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://tailwindcss.com/docs/utility-first"&gt;the official site&lt;/a&gt;, this way of composing styles is called &lt;strong&gt;Utility-First&lt;/strong&gt;. Utility-First CSS frameworks offer these merits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You don't have to name classes by yourself.&lt;/strong&gt; A traditional approach would invent and apply a class name to each component that needs to be styled. With Tailwind CSS, you just use predefined class names whenever you want to apply styles to the DOM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS doesn't grow.&lt;/strong&gt; With a traditional approach, new CSS is added every time you have a new component to be styled. With Tailwind CSS, you always use the same set of predefined styles so your CSS doesn't grow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styles are kept local.&lt;/strong&gt; A traditional approach would allow using a single class from multiple elements, or writing  selectors that indirectly affects descendant elements (like &lt;code&gt;.cls div&lt;/code&gt;). Such situations make it hard to predict how a style change affects to your whole app. With Tailwind CSS, your styles are tightly tied to specific DOM elements. Also, Tailwind classes don't have the indirect effects. These characteristics keep the styles local so that making changes to styles are safe.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the other hand, the author doesn't feel good about how &lt;strong&gt;Tailwind CSS isn't CSS while it is based on CSS&lt;/strong&gt;. As seen in the example above, Tailwind CSS consists of utility classes made by abbreviating and abstracting pure CSS concepts, which means that you have to memorize Tailwind-specific vocabulary. However, this does &lt;em&gt;not&lt;/em&gt; mean that you don't have to learn pure CSS in order to use Tailwind CSS. If you don't know how CSS's padding works, you can't understand Tailwind's &lt;code&gt;p-8&lt;/code&gt;! Moreover, Tailwind CSS doesn't offer full CSS features through its predefined utility classes. To use modern CSS features, Tailwind CSS isn't sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lightwind CSS Lets You Use Plain CSS
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Lightwind CSS&lt;/strong&gt;, the CSS framework created by the author, is designed so that it offers all the merits from Tailwind CSS and also allows use of the plain CSS. For example, you write styles with Lightwind CSS as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="s2"&gt;`
    display: flex;
    flex-flow: row nowrap;
    justify-content: center;
  `&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="s2"&gt;`
      display: flex;
      flex-flow: column nowrap;
      justify-content: center;
      align-items: center;
    `&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    Hello, world!
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly to Tailwind, you attach CSS directly to HTML elements. The &lt;code&gt;css&lt;/code&gt; function receives a CSS string and returns corresponding class names. The syntax is actually the same as &lt;a href="https://emotion.sh/docs/introduction"&gt;emotion's &lt;code&gt;css&lt;/code&gt; API&lt;/a&gt;. This reduces the need of inventing class names similarly to how Tailwind does so. It also helps keep the styles local.&lt;/p&gt;

&lt;p&gt;The key feature of Lightwind CSS is the ability to globally optimize CSS for production builds. Lightwind CSS generates one CSS file that contains all the styles in your app. A CSS file that corresponds to the above code would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.c&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The markup would be transformed into the following by Lightwind CSS's Babel plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a b"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a c"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of note is that Lightwind CSS has optimizes globally; styles from two distinct &lt;code&gt;css&lt;/code&gt; are detected and named &lt;code&gt;a&lt;/code&gt;, and &lt;code&gt;a&lt;/code&gt; is shared by two HTML elements. Usage of &lt;code&gt;css&lt;/code&gt; from different files would also be properly optimized. This feature lets us prevent CSS from growing. You may write the same styles in different places, and they are all optimized into one by Lightwind CSS.&lt;/p&gt;

&lt;p&gt;In summary, Lightwind CSS takes an opposite approach to Tailwind CSS. While Tailwind CSS first defines the set of class names to be used, Lightwind CSS lets you write arbitrary CSS and then calculate the optimized set of class names from what you wrote. This way, Lightwind CSS still provides you the three merits while not forcing you to remember Tailwind-specific classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison to Plain Inline Styles
&lt;/h2&gt;

&lt;p&gt;Lightwind CSS' way of writing styles is close to writing plain inline styles, that is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;flexFlow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;row nowrap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actually, the documents of Tailwind CSS discusses it in the section named &lt;em&gt;Why not just use inline styles?&lt;/em&gt;, as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tailwind CSS offers abstracted styles like &lt;code&gt;p-8&lt;/code&gt; or &lt;code&gt;rounded-xl&lt;/code&gt; instead of using concrete numbers like &lt;code&gt;padding: 0.75rem;&lt;/code&gt; or &lt;code&gt;border-radius: 8px;&lt;/code&gt;. This helps you easily build consistent designs.&lt;/li&gt;
&lt;li&gt;Media queries cannot be used with inline styles. Tailwind CSS offers media queries-aware classes like &lt;code&gt;md:flex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pseudo classes (like &lt;code&gt;:hover&lt;/code&gt; or &lt;code&gt;:focus&lt;/code&gt;) can neither be used with inline styles. Tailwind CSS also offers classes like &lt;code&gt;hover:bg-purple-700&lt;/code&gt; for this use case.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lightwind CSS solves 2 and 3 by allowing nested rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="s2"&gt;`
      display: flex;
      flex-flow: column nowrap;
      justify-content: center;
      align-items: center;

      &amp;amp;:hover {
        opacity: 0.5;
      }
    `&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    Hello, world!
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, Lightwind CSS excludes the first point -- consistent designs -- from its responsibility, on purpose. This is because we want to provide the experience of writing plain CSS. Building a consistent design system is now your duty.&lt;/p&gt;

&lt;p&gt;If you need theming, CSS Variable should be useful. Lightwind CSS might provide a helper to utilize CSS Variables easily in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notes on Nested Rules
&lt;/h3&gt;

&lt;p&gt;As described above, Lightwind CSS supports nested CSS rules. Please note that it allows you to break the CSS locality, which is one of the goodness of Lightwind CSS that is inherited from Tailwind. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="s2"&gt;`
      display: flex;
      flex-flow: column nowrap;
      justify-content: center;
      align-items: center;

      /* This is not local, affects
       * all the p elements under this!
       */
      p {
        color: red;
      }
    `&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    Hello, world!
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may be seen as Lightwind CSS offering more freedom on breaking the locality. Lightwind CSS a light utility so it doesn't restrict a lot of things.&lt;/p&gt;

&lt;p&gt;If you want that restriction (I recommend to do so!), you can utilize linters like stylelint to ban the above pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article introduced &lt;strong&gt;Lightwind CSS&lt;/strong&gt;, a CSS framework that offers the same goodness as Tailwind CSS and lets you write plain CSS instead of Tailwind-specific class names. The key feature of Lightwind CSS is the global optimization to generate one optimized class definitions.&lt;/p&gt;

</description>
      <category>css</category>
      <category>react</category>
    </item>
    <item>
      <title>A Concurrent Mode-Safe Version of useRef</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Wed, 22 Apr 2020 15:20:49 +0000</pubDate>
      <link>https://dev.to/uhyo_/a-concurrent-mode-safe-version-of-useref-1325</link>
      <guid>https://dev.to/uhyo_/a-concurrent-mode-safe-version-of-useref-1325</guid>
      <description>&lt;p&gt;When you use React Hooks, components maintain internal states for hooks. For example, caches made by &lt;code&gt;useMemo&lt;/code&gt; and objects returned by &lt;code&gt;useRef&lt;/code&gt; are also residents of the internal state, as well as states controlled by the &lt;code&gt;useState&lt;/code&gt; hook. During a rendering of a component, the internal states of that component are updated. The &lt;code&gt;useMemo&lt;/code&gt; hook should be one of the easiest example of updates during a rendering. Caches of &lt;code&gt;useMemo&lt;/code&gt; are updated immediately during a &lt;code&gt;useMemo&lt;/code&gt; call, if necessary.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html"&gt;React's Concurrent Mode&lt;/a&gt;, components have possibility of suspension. That is, a rendering of a component does not necessarily result in a DOM update (or other view updates if you are not using &lt;code&gt;react-dom&lt;/code&gt;). Every time a component suspends, modifications made during the rendering that suspended are rolled back to the state before rendering. For example, a cache newly made by &lt;code&gt;useMemo&lt;/code&gt; is discarded if that rendering suspends.&lt;/p&gt;

&lt;p&gt;From this characteristic of Concurrent Mode, it follows that we ought to take extra care on usage of the &lt;code&gt;useRef&lt;/code&gt; hook. The role of &lt;code&gt;useRef&lt;/code&gt; is very simple; it always returns the same object (ref object; more accurately, an object that is made on the first rendering of that component). This object can be utilized for communication between rendering or any other side effects that originate from a component. The point is that, modifications made to the ref object is not rolled back even if a rendering suspends.&lt;/p&gt;

&lt;p&gt;In an article &lt;a href="https://medium.com/better-programming/how-to-properly-use-the-react-useref-hook-in-concurrent-mode-38c54543857b"&gt;How To Properly Use the React useRef Hook in Concurrent Mode&lt;/a&gt; by Daishi Kato, a usage of &lt;code&gt;useRef&lt;/code&gt; where a ref object is modified during a rendering is regarded as a Bad Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BadCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The counter's value is increased every time the &lt;code&gt;BadCounter&lt;/code&gt; is rendered. Of note is that, in Concurrent Mode, this may not match with how many times the contents of &lt;code&gt;BadCounter&lt;/code&gt; is reflected to the DOM.&lt;/p&gt;

&lt;p&gt;In a worse situation the current value of a ref object may interact with other hooks during a rendering. If such a rendering suspends, the component logic may fall into an inconsistent state where the ref object's value reflects the suspended rendering's state while other hooks' state are reset.&lt;/p&gt;

&lt;p&gt;Therefore, to involve &lt;code&gt;useRef&lt;/code&gt; in a rendering logic, we need a concurrent-mode safe version of &lt;code&gt;useRef&lt;/code&gt;, whose value is automatically rolled back if  a rendering suspends. In other words, it is more like a variant of &lt;code&gt;useState&lt;/code&gt; which does not trigger re-rendering.&lt;/p&gt;

&lt;p&gt;Here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Raw&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;isRendering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;comittedValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useConcurrentModeSafeRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Raw&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Raw&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rawRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;rawRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;isRendering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;comittedValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRendering&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;committedValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRendering&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comittedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRendering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRendering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comittedValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comittedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;useConcurrentModeSafeRef&lt;/code&gt; returns an object with the same signature as &lt;code&gt;useRef&lt;/code&gt;. The intended usage is to use &lt;code&gt;ref.current&lt;/code&gt; as a storage that is persistent between renderings. Every time &lt;code&gt;useConcurrentModeSafeRef&lt;/code&gt; is called, the &lt;code&gt;current&lt;/code&gt; is reset to &lt;code&gt;raw.committedValue&lt;/code&gt;. This value is updated only when a rendering succeeds; this behavior is realized with the help of &lt;code&gt;useEffect&lt;/code&gt; hook. If a rendering suspends, &lt;code&gt;raw.committedValue&lt;/code&gt; stays in the old state so that the changes made during that rendering are to be discarded.&lt;/p&gt;

&lt;p&gt;The ref object returned by &lt;code&gt;useConcurrentModeSafeRef&lt;/code&gt; behaves the same as &lt;code&gt;useRef&lt;/code&gt; outside of renderings. Users can directly interact with &lt;code&gt;raw.committedValue&lt;/code&gt; in such situations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article explained a Concurrent Mode-safe variant of &lt;code&gt;useRef&lt;/code&gt;. The key of the Concurrent Mode safety is that the value of ref objects are rolled back if a rendering suspends for aligned behavior with other hooks.&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>Implementing CSS Animations with New Experimental useTransition Hook</title>
      <dc:creator>🈚️うひょ🤪</dc:creator>
      <pubDate>Thu, 19 Dec 2019 16:08:10 +0000</pubDate>
      <link>https://dev.to/uhyo_/implementing-css-animations-with-new-experimental-usetransition-hook-4g0e</link>
      <guid>https://dev.to/uhyo_/implementing-css-animations-with-new-experimental-usetransition-hook-4g0e</guid>
      <description>&lt;p&gt;This is a summarized version of a Japanese article by the same author:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qiita.com/uhyo/items/edd51ca053ed0e7ae83d" rel="noopener noreferrer"&gt;ワイ「アニメーションするにはこのuseTransitionってのを使えばええんか？」&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In October 2019, the React team introduced an experimental preview of &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html" rel="noopener noreferrer"&gt;React's new Concurrent Mode&lt;/a&gt;. Along with other innovative (but a little bit opinionated) features in it, the new &lt;strong&gt;useTransition&lt;/strong&gt; hook has power to completely change how we develop React applications.&lt;/p&gt;

&lt;p&gt;Here is a brief introduction of the &lt;code&gt;useTransition&lt;/code&gt; hook (see the official docs for more details): the &lt;code&gt;useTransition&lt;/code&gt; hook allows us to maintain two states at the same time, primarily designed for page transitions.&lt;/p&gt;

&lt;p&gt;Consider a situation where you update some state in order to transition to a new page. In Concurrent Mode, the rendering of the new state may “suspend” (typically due to data fetching). Without &lt;code&gt;useTransition&lt;/code&gt;, we have to render fallback contents (often a loading icon) during the suspension. What is important here is that the suspension can only be detected &lt;em&gt;after&lt;/em&gt; state updates, since suspension occurs as a result of rendering based on the new state.&lt;/p&gt;

&lt;p&gt;By utilizing &lt;code&gt;useTransition&lt;/code&gt;, we can tell React to keep reflecting the old state to the DOM while suspension. As soon as the rendering of the new state completes, React switches the DOM to the new result. Furthermore, &lt;code&gt;useTransition&lt;/code&gt; provides a flag of whether it is pending (waiting for the rendering of the new state) to the world of the old state. Here React is maintaining two worlds at the same time: one for the old pending state and one for the new state.&lt;/p&gt;

&lt;p&gt;You can find nice examples of &lt;code&gt;useTransition&lt;/code&gt; at &lt;a href="https://reactjs.org/docs/concurrent-mode-patterns.html#transitions" rel="noopener noreferrer"&gt;the official documents&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using useTransition for Animations
&lt;/h2&gt;

&lt;p&gt;As is obvious from its name, the &lt;code&gt;useTransition&lt;/code&gt; hook is fairly useful for implementing CSS animations based on the &lt;code&gt;transition&lt;/code&gt; CSS property. This article shows how to use &lt;code&gt;useTransiton&lt;/code&gt; for this purpose and gives a brief explanation.&lt;/p&gt;

&lt;p&gt;The well-known problem regarding CSS animations in React is how to handle mounting and unmounting of components. If we want to utilize CSS transitions, we cannot mount a new DOM element and start its animation in one action; we have to mount an element in the before-animation state first, and then immediately alter its style to after-animation one to trigger the animation.&lt;/p&gt;

&lt;p&gt;Previously, people used libraries like &lt;a href="https://github.com/reactjs/react-transition-group" rel="noopener noreferrer"&gt;react-transition-group&lt;/a&gt; or &lt;a href="https://www.react-spring.io/" rel="noopener noreferrer"&gt;react-spring&lt;/a&gt; to handle this situation. These libraries automates the above two-step state changes.&lt;/p&gt;

&lt;p&gt;In this article, an alternative approach which utilizes &lt;code&gt;useTransition&lt;/code&gt; is introduced. Below is an example though it is still a rough PoC:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/qiita-wai-react-2-uj246"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the example, you can click the &lt;code&gt;toggle&lt;/code&gt; button to show and hide a blue box. The box animates its &lt;code&gt;opacity&lt;/code&gt; on every state change and is actually mounted/unmounted every time. As usual, unmounting is delayed until the animation completes. In what follows, the trick used in this example is explained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;We start from looking at some utilities defined in the example. The first is the &lt;code&gt;Timer&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/Timer.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;throwIfNotDone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;new Timer(duration)&lt;/code&gt; creates a Promise which is fulfilled after &lt;code&gt;duration&lt;/code&gt; milliseconds. The &lt;code&gt;throwIfNotDone&lt;/code&gt; method, when called, throws that Promise if it is not fulfilled yet. We don't step into details, but throwing Promises is a significant characteristic of React's Concurrent Mode. In short, throwing a Promise means that the current rendering should be suspended until that Promise is fulfilled.&lt;/p&gt;

&lt;p&gt;So we need a component that actually throws this Promise. It's called &lt;code&gt;Waiter&lt;/code&gt; in the example. It can't be simpler; it receives a Timer from props and calls its &lt;code&gt;throwIfNotDone&lt;/code&gt; method. It does not produce actual contents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Waiter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;throwIfNotDone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React has a rule that, if a component may throw a Promise it must be enclosed in React's &lt;code&gt;Suspense&lt;/code&gt; component. That's why &lt;code&gt;Waiter&lt;/code&gt; is used as follows in the example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Waiter&lt;/span&gt; &lt;span class="na"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to &lt;code&gt;Timer&lt;/code&gt; and &lt;code&gt;Waiter&lt;/code&gt;, we now have ability to cause suspensions for a certain period of time while rendering. In the example we prepare the &lt;code&gt;timer&lt;/code&gt; state which is passed to &lt;code&gt;Waiter&lt;/code&gt;. If you create a &lt;code&gt;Timer&lt;/code&gt; and set the &lt;code&gt;timer&lt;/code&gt; state to it, the next rendering would be suspended for the specified time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two-Step Rendering Using useTransition
&lt;/h2&gt;

&lt;p&gt;Now, let's see how the animation is implemented in the example. First of all, the blue box is rendered by the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;show&lt;/code&gt; is a boolean state and &lt;code&gt;isPending&lt;/code&gt; is a flag provided by &lt;code&gt;useTransition&lt;/code&gt; indicating whether some rendering is suspended now. Normally &lt;code&gt;isPending&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; and it becomes &lt;code&gt;true&lt;/code&gt; only while suspension.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Box&lt;/code&gt; component renders a blue box; if &lt;code&gt;show={false}&lt;/code&gt; its &lt;code&gt;opacity&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt; and if &lt;code&gt;show={true}&lt;/code&gt; its &lt;code&gt;opacity&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;. It is worth noting that the &lt;code&gt;Box&lt;/code&gt; component is actually unmounted while &lt;code&gt;show&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally we see what happens when we click the &lt;code&gt;toggle&lt;/code&gt; button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setShow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setShow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;show&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, we call &lt;code&gt;setShow(true)&lt;/code&gt;, which will update &lt;code&gt;state&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;. The point is the &lt;code&gt;startTransition&lt;/code&gt; call following it; it takes a callback function which is immediately called. The &lt;code&gt;useTransition&lt;/code&gt; hook works for the states updated inside the callback; if these state updates caused a suspension, then React renders the old state while setting &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;isPending&lt;/code&gt; during the suspension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2la945mm8ucj1566vzxr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2la945mm8ucj1566vzxr.jpeg" alt="Illustration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is an illustration of what happens here. In the initial state (the left box in the above image) both &lt;code&gt;show&lt;/code&gt; and &lt;code&gt;isPending&lt;/code&gt; are false. When &lt;code&gt;toggle()&lt;/code&gt; is called, &lt;code&gt;show&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt; as usual. Also, &lt;code&gt;timer&lt;/code&gt; is set to &lt;code&gt;new Timer(10)&lt;/code&gt; inside &lt;code&gt;startTransition&lt;/code&gt;. As explained above, this will trigger a suspension which leads to the middle state (where &lt;code&gt;show&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;isPending&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;) being rendered to the DOM. After 10ms the suspension finishes and the last state (&lt;code&gt;show&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;isPending&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;) is rendered.&lt;/p&gt;

&lt;p&gt;Here we achieved the two-step rendering with one set of state updates by cleverly utilizing suspension and &lt;code&gt;isPending&lt;/code&gt; provided by &lt;code&gt;useTransition&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;Next we see what happens when &lt;code&gt;trigger()&lt;/code&gt; is called while &lt;code&gt;show&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;      &lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setShow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3gokx0evfob3xt52anwq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3gokx0evfob3xt52anwq.jpeg" alt="Illustration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the initial state &lt;code&gt;show&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;isPending&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;. Basically we are doing the same: set &lt;code&gt;show&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; and set a &lt;code&gt;Timer&lt;/code&gt;. This time the duration of timer is 500 ms; this is the duration of the animation of &lt;code&gt;opacity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The point is that, this time the update for &lt;code&gt;show&lt;/code&gt; is also put inside &lt;code&gt;startTransition&lt;/code&gt;. Thanks to this, the value of &lt;code&gt;show&lt;/code&gt; keeps the old one while the suspension caused by &lt;code&gt;timer&lt;/code&gt;. This is why in the middle state &lt;code&gt;show&lt;/code&gt; is still &lt;code&gt;true&lt;/code&gt; while &lt;code&gt;isPending&lt;/code&gt; is updated to &lt;code&gt;true&lt;/code&gt;. After 500 ms it transitions to the last state where &lt;code&gt;show&lt;/code&gt; is updated to &lt;code&gt;false&lt;/code&gt; and &lt;code&gt;isPending&lt;/code&gt; is set back to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article explained how to utilize &lt;code&gt;useTransition&lt;/code&gt; from React's Concurrent Mode to implement CSS animations. Thanks to the &lt;code&gt;isPending&lt;/code&gt; flag provided by it, we can pack a two-step rendering into one set of state updates.&lt;/p&gt;

</description>
      <category>react</category>
    </item>
  </channel>
</rss>
