<?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: selbekk</title>
    <description>The latest articles on DEV Community by selbekk (@selbekk).</description>
    <link>https://dev.to/selbekk</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%2F143337%2Fd2ce5b9d-a56e-428a-8daf-e9b97dce46a8.jpg</url>
      <title>DEV Community: selbekk</title>
      <link>https://dev.to/selbekk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/selbekk"/>
    <language>en</language>
    <item>
      <title>Terminal illness</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Sun, 05 Jul 2020 11:22:27 +0000</pubDate>
      <link>https://dev.to/selbekk/terminal-illness-c61</link>
      <guid>https://dev.to/selbekk/terminal-illness-c61</guid>
      <description>&lt;p&gt;You don't have to be a Linux hacker to use the terminal to be productive. Here's a few tips I've picked up the last couple of years that might make you even iller in the terminal.&lt;/p&gt;

&lt;p&gt;Just a disclaimer - I'm no terminal professional. Yet, over the 7 last years, I've learned a few very nice-to-know techniques that you might not have heard of. There's no guarantee that you'll learn anything from this, but a pretty bit chunk of my readers might learn at least a thing or two.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A little side note here - these commands are meant for OSX only. They might work on Linux or WLS, but I haven't tried them out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Use the clipboard!
&lt;/h2&gt;

&lt;p&gt;Every once in a while, you have some data in the clipboard that you want to use somehow, or you want to copy the output of a command into the clipboard. Either way - it's very possible to do!&lt;/p&gt;

&lt;p&gt;So there are two commands you need to know - &lt;code&gt;pbcopy&lt;/code&gt; and &lt;code&gt;pbpaste&lt;/code&gt;. You can use them together with the pipe operator &lt;code&gt;|&lt;/code&gt; and the "to file" operator &lt;code&gt;&amp;gt;&lt;/code&gt; to do really cool stuff. &lt;/p&gt;

&lt;p&gt;Here's a few examples:&lt;/p&gt;

&lt;p&gt;To paste whatever is in your clipboard into a new file - let's say &lt;code&gt;.env&lt;/code&gt; - you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pbpaste &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more creating a new file, then opening it in vim or VSCode to paste and save - now you can just type a few characters and get the job done!&lt;/p&gt;

&lt;p&gt;Similarly, if you want to copy a file to the clipboard, you use the pipe operator and &lt;code&gt;pbcopy&lt;/code&gt;. This is how it looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .env | pbcopy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cat&lt;/code&gt; echoes out the entire contents of a file (in this instance &lt;code&gt;.env&lt;/code&gt;) and the pipe operator passes it as input to the &lt;code&gt;pbcopy&lt;/code&gt; command. Voilá - now you can copy the content of entire files without opening them!&lt;/p&gt;

&lt;p&gt;I use this all the time when I need to copy my ssh key and paste it into GitHub or BitBucket. &lt;/p&gt;

&lt;p&gt;You don't have to limit yourself to files though - &lt;code&gt;pbcopy&lt;/code&gt; is much more flexible than that. Whatever you pipe in can be placed on the clipboard - so if you want to copy the result of a program (let's say an encryption program or &lt;code&gt;pwd&lt;/code&gt;), you just pipe it on in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing more with &lt;code&gt;less&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I often use the tiny file reader program &lt;code&gt;less&lt;/code&gt; to scan, search and read through files. It's really powerful if you know how to use it, but even if you're just using it for the first time, you can just use the arrow keys on your keyboard to scroll through files directly in the terminal.&lt;/p&gt;

&lt;p&gt;Now, I use this mostly to read configuration files, and if I come across something I need to change, I've always had to close the file I was looking at, and open it in an editor like vim. &lt;/p&gt;

&lt;p&gt;Luckily - you can just type &lt;code&gt;v&lt;/code&gt;, and the default editor (typically &lt;code&gt;vim&lt;/code&gt;) opens up, focused on the same line you were at. Once you close &lt;code&gt;vim&lt;/code&gt; (provided you know how to close &lt;code&gt;vim&lt;/code&gt;), you're placed back in the same spot as you were as well.&lt;/p&gt;

&lt;p&gt;Also - you can go the start of the document with &lt;code&gt;g&lt;/code&gt;, and to the end with &lt;code&gt;shift+g&lt;/code&gt;. You can search for a phrase by tapping &lt;code&gt;/&lt;/code&gt;, and typing out whatever you're looking for. Navigate through the occurrences by &lt;code&gt;n&lt;/code&gt; (forward) and &lt;code&gt;shift+n&lt;/code&gt; (backwards). And there's a ton of other things you can do (which you can read about &lt;a href="https://www.linode.com/docs/quick-answers/linux/how-to-use-less/"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Open files and folders with open
&lt;/h2&gt;

&lt;p&gt;Often times, you stumble across a file you want want to open the file's default application. That might be a video, an audio clip or perhaps a CSV file. You could exit the flow you're in, of course, and use Finder to navigate to your file and double click it - but we can do better.&lt;/p&gt;

&lt;p&gt;If you want to open any file, you can use the open command to get it done from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;open videos/screen_recording.mp4
&lt;span class="nv"&gt;$ &lt;/span&gt;open package.json
&lt;span class="nv"&gt;$ &lt;/span&gt;open images/vacation.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I usually don't open a lot of files this way, but I do open folders! Just use open on any folder, and you'll get started right away!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;open ~/Documents
&lt;span class="nv"&gt;$ &lt;/span&gt;open &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="c"&gt;# opens the current folder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Some power characters!-
&lt;/h2&gt;

&lt;p&gt;There are two really nice characters to know when using the terminal, and those two are &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;!&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-&lt;/code&gt; character (dash, hyphen, whatever you call it) works well in two contexts. You can add it to the &lt;code&gt;cd&lt;/code&gt; command to return to the previous directory you were in, and you can add it to git checkout to check out the previous branch you were on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example of using cd -&lt;/span&gt;
~/Documents &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/bin
/usr/bin &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; -
~/Documents &lt;span class="err"&gt;$&lt;/span&gt;

&lt;span class="c"&gt;# Example of using git checkout -&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;git checkout feature-branch
&lt;span class="o"&gt;(&lt;/span&gt;feature-branch&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;git checkout -
&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exclamation mark is also pretty neat - it lets you search the history of command you've done previously, or re-use the arguments to the last command you used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="c"&gt;# shows you the last command you ran that started with cat&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;less a.txt b.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;vim &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="c"&gt;# opens a.txt and b.txt in vim&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;less a.txt b.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;vim &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="c"&gt;# opens b.txt in vim&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a neat little trick that I know for some reason, but I never use. Perhaps you'll find some use for it though!&lt;/p&gt;

&lt;p&gt;Much more usable, however is the double exclamation point! Especially in conjunction with the sudo command. If you've ever run a command and realized you had to run it as an administrator, you can simply do &lt;code&gt;sudo !!&lt;/code&gt; and re-run it with sudo!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/share/firmlinks
&lt;span class="nb"&gt;chmod&lt;/span&gt;: Unable to change file mode on /usr/share/firmlinks: Operation not permitted
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="c"&gt;# Now it works!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Searching the command history
&lt;/h3&gt;

&lt;p&gt;Speaking of command history - you don't really need the ! command when you know about the &lt;code&gt;ctrl+r&lt;/code&gt; shortcut! Tap it once, and you'll be able to do an interactive autocomplete search of your entire command history!&lt;/p&gt;

&lt;h2&gt;
  
  
  Oh my...
&lt;/h2&gt;

&lt;p&gt;Lastly, I want to talk about &lt;code&gt;oh-my-zsh&lt;/code&gt;. Zsh (pronounced sea shell) is a popular alternative to the well known bash shell, and oh-my-zsh is a small framework that adds a ton of useful functionality, aliases and plugins to make your workflow as smooth as possible.&lt;/p&gt;

&lt;p&gt;If you haven't installed it already, you can do so by visiting their &lt;a href="https://ohmyz.sh/"&gt;home page&lt;/a&gt;. Next, pop up this cheat sheet and start learning. There's a ton of useful shortcuts for git (like &lt;code&gt;gst&lt;/code&gt; for &lt;code&gt;git status&lt;/code&gt; and &lt;code&gt;gc&lt;/code&gt; for git commit), but also really nifty commands like &lt;code&gt;...&lt;/code&gt; for navigating two directories up or &lt;code&gt;take deep/directory/tree&lt;/code&gt; for creating a new directory and navigating into it.&lt;/p&gt;

&lt;p&gt;In addition, there are tons of great themes and plugins available to make your terminal super powerful. I've had oh-my-zsh installed for years, and I just love it more for every passing day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last words
&lt;/h2&gt;

&lt;p&gt;These are some of my favorite tips for being productive in the terminal. There are tons of stuff I've skipped - like how to grep or exit vim - but to be honest I don't use those a lot either. I hope you found at least one new technique to add to your roster - and that you promise to share your favorite commands with your fellow readers in the comments section.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Forwarding refs in TypeScript</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Mon, 18 May 2020 08:23:41 +0000</pubDate>
      <link>https://dev.to/selbekk/forwarding-refs-in-typescript-elp</link>
      <guid>https://dev.to/selbekk/forwarding-refs-in-typescript-elp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally posted on my blog - &lt;a href="https://www.selbekk.io/blog/2020/05/forwarding-refs-in-typescript/"&gt;selbekk.io&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you're working on a component library, or just creating reusable components in general, you often end up creating small wrapper components that only adds a css class or two. Some are more advanced, but you still need to be able to imperatively focus them.&lt;/p&gt;

&lt;p&gt;This used to be a hard problem to solve back in the days. Since the ref prop is treated differently than others, and not passed on to the component itself, the community started adding custom props named &lt;code&gt;innerRef&lt;/code&gt; or &lt;code&gt;forwardedRef&lt;/code&gt;. To address this, React 16.3 introduced the &lt;code&gt;React.forwardRef API&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;forwardRef&lt;/code&gt; API is pretty straight-forward. You wrap your component in a function call, with is passed props and the forwarded ref, and you're then supposed to return your component. Here's a simple example in JavaScript:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;forwardedRef&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;forwardedRef&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="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then use this component like ref was a regular prop:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;return&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;Button&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    A button
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use forwardRef with TypeScript
&lt;/h2&gt;

&lt;p&gt;I always screw this up, so I hope by writing this article I can help both you and me to figure this out.&lt;/p&gt;

&lt;p&gt;The correct way to type a &lt;code&gt;forwardRef&lt;/code&gt;-wrapped component 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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&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;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;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;props&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or more generally:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;TheReferenceType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;ThePropsType&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;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;forwardedRef&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CustomComponentOrHtmlElement&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;forwardedRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was a bit un-intuitive at first, because it looks like you can pass a regular component to ForwardRef. However, regular components don't accept a second ref parameter, so the typing will fail.&lt;/p&gt;

&lt;p&gt;I can't count how often I've done this mistake:&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&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;Button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RefForwardingComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Props&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;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a mistake, because the RefForwardingComponent is the type of the render function you create (the one that receives props and ref as arguments), and not the result of calling React.forwardRef.&lt;/p&gt;

&lt;p&gt;In other words - &lt;strong&gt;remember to pass your type variables directly to &lt;code&gt;React.forwardRef&lt;/code&gt;&lt;/strong&gt;! It will automatically return the correct type for you.&lt;/p&gt;

&lt;p&gt;Another gotcha is the order of the type variables - it's the ref type first, then the props type. It's kind of counter-intuitive to me, since the arguments to the render function is the opposite (props, ref) - so I just remember it's the opposite of what I'd guess. 😅&lt;/p&gt;

&lt;p&gt;I hope this article helped you figure out this pesky typing issue that have gotten me so many times in a row. Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Setting Up a Development Environment in Elm</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Sun, 16 Feb 2020 11:45:09 +0000</pubDate>
      <link>https://dev.to/selbekk/setting-up-a-development-environment-in-elm-4gpf</link>
      <guid>https://dev.to/selbekk/setting-up-a-development-environment-in-elm-4gpf</guid>
      <description>&lt;p&gt;As I was building out yet another Elm test project, I wanted to add some CSS to my app. I added a &lt;code&gt;styles.css&lt;/code&gt; file to my source folder, and soon realized I had nowhere to include it! I've always been running &lt;code&gt;elm reactor&lt;/code&gt; up until this point, but that doesn't give me access to any styles whatsoever.&lt;/p&gt;

&lt;p&gt;After looking in the &lt;a href="https://guide.elm-lang.org/webapps/"&gt;docs&lt;/a&gt;, I found I could use &lt;code&gt;elm make&lt;/code&gt; to create a default HTML file for me, but that meant that I had to build my project on every change to iterate on my application. Surely, there's a better approach out there?&lt;/p&gt;

&lt;p&gt;Turns out, the options weren't documented very well, but they're definitely out there! This article will show you a few different ways you can set up a development environment for a real world application, complete with hot reloading and all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started: Hello again, NPM
&lt;/h2&gt;

&lt;p&gt;The first thing you'll need to do, is to run &lt;code&gt;npm init&lt;/code&gt; (alternatively &lt;code&gt;yarn init&lt;/code&gt;) to bootstrap a &lt;code&gt;package.json&lt;/code&gt; file. I thought I wouldn't have to use a JavaScript package manager for Elm apps, but in order to set up a development environment, you definitely need to.&lt;/p&gt;

&lt;p&gt;In any real world application, you'll probably need some JavaScript libraries at some point, too, so don't feel bad about adding it. You'll still be writing Elm most of the time!&lt;/p&gt;

&lt;h2&gt;
  
  
  The naïve approach - automation!
&lt;/h2&gt;

&lt;p&gt;The simplest approach I could come up with is to set up a file watcher that runs &lt;code&gt;elm make --output public/app.js&lt;/code&gt; on every change in my Elm files. I went with &lt;a href="https://www.npmjs.com/package/watch"&gt;&lt;code&gt;watch&lt;/code&gt;&lt;/a&gt;, an &lt;code&gt;npm&lt;/code&gt; package, and added the following to my &lt;code&gt;package.json&lt;/code&gt;:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="s2"&gt;"watch &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;elm make src/Main.elm --output=public/app.js&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; src/**/*.elm"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I can create an &lt;code&gt;index.html&lt;/code&gt; file in the &lt;code&gt;public/&lt;/code&gt; directory, and add my CSS file next to it. When I'm done, my file structure will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
 - Main.elm
 - OtherFiles.elm
public
 - index.html
 - styles.css
 - app.js
package.json
elm.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;index.html&lt;/code&gt; file is super basic, and will look like this:&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 Elm app&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./styles.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="nt"&gt;/&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&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;"app.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;script&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Elm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&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, I can open the &lt;code&gt;public/&lt;/code&gt; folder with i.e. &lt;a href="https://www.npmjs.com/package/serve"&gt;&lt;code&gt;serve&lt;/code&gt;&lt;/a&gt;, and iterate on my app like it ain't no thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Elm approach: &lt;code&gt;elm-live&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Even if the above approach technically works, it feels like I've built something with toothpicks and band-aids. Surely, there's something a bit more put together?&lt;/p&gt;

&lt;p&gt;Luckily, there is. &lt;a href="https://github.com/wking-io/elm-live"&gt;&lt;code&gt;elm-live&lt;/code&gt;&lt;/a&gt; is the all-Elm alternative that provides us with iterative builds, hot module reloading and a ton of other features. &lt;/p&gt;

&lt;p&gt;To get started, install it with &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&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 &lt;span class="nb"&gt;install &lt;/span&gt;elm-live
yarn add elm-live
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to add a script to our &lt;code&gt;package.json&lt;/code&gt; file:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="s2"&gt;"elm-live src/Main.elm --hot --start-page=public/custom.html -- --output=public/app.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Start your script, and a hot-reloading dev server will pop up and instantly improve your developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  My favorite approach: Parcel
&lt;/h2&gt;

&lt;p&gt;Although the &lt;code&gt;elm-live&lt;/code&gt; approach is nice and all, we still need to have a bunch of manually edited stuff inside of our &lt;code&gt;public/&lt;/code&gt; folder. Wouldn't it be nice if some build tool figured all of this out for us?&lt;/p&gt;

&lt;p&gt;Meet &lt;a href="https://parceljs.org/"&gt;Parcel&lt;/a&gt;. Parcel is a bundler for web apps, which happens to support Elm out of the box. In addition, it works with JavaScript, CSS and other resources as well, which will help us a lot down the road. Let's give it a try!&lt;/p&gt;

&lt;p&gt;First off, let's install it with your package manager of choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;parcel-bundler
yarn add parcel-bundler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, move your hand-crafted &lt;code&gt;public/styles.css&lt;/code&gt; and &lt;code&gt;public/index.html&lt;/code&gt; into your &lt;code&gt;src&lt;/code&gt; folder. They're source code, after all! We'll create an additional file, &lt;code&gt;index.js&lt;/code&gt;, which will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Elm } from './Main.elm';
import './styles.css';

Elm.Main.init({
  node: document.getElementById('root')
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets us remove the inline script tag from our HTML file, as well as the &lt;code&gt;&amp;lt;link /&amp;gt;&lt;/code&gt; CSS tag.&lt;/p&gt;

&lt;p&gt;Finally, let's add the script to our start tag:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"parcel src/index.html"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's nothing more to it. Run your script, and you'll notice a hot-reloading dev server pop up for you, just like you'd expect. This will even include an Elm debugger tool as well 😎&lt;/p&gt;

&lt;p&gt;A nice bonus feature with Parcel, is that you'll be able to add styles processing and JavaScript transpilation in no time at all. That's nice to know!&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it!
&lt;/h2&gt;

&lt;p&gt;Turns out, setting up a nice developer experience isn't a lot of work, once you know what to do. I hope this article can help future beginners like myself looking for the best way to get started. &lt;/p&gt;

&lt;p&gt;Please let me know how you set up your dev environment in the comments!&lt;/p&gt;

</description>
      <category>elm</category>
      <category>functional</category>
      <category>parcel</category>
    </item>
    <item>
      <title>Dad jokes and HTTP requests in Elm</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Thu, 02 Jan 2020 23:18:24 +0000</pubDate>
      <link>https://dev.to/selbekk/dad-jokes-and-http-requests-in-elm-5198</link>
      <guid>https://dev.to/selbekk/dad-jokes-and-http-requests-in-elm-5198</guid>
      <description>&lt;p&gt;What does the Elm developer say when asked to go out to party? &lt;code&gt;Maybe&lt;/code&gt;. Oh yes. Welcome to the shit show that is my dad joke game 😎&lt;/p&gt;

&lt;p&gt;After creating both &lt;a href="https://dev.to/selbekk/my-first-elm-app-c70"&gt;a counter&lt;/a&gt; and &lt;a href="https://dev.to/selbekk/creating-a-todo-app-in-elm-i3o"&gt;a todo app&lt;/a&gt; in Elm, I'm ready to go for the big leagues. Create that real business value. Satisfy the client needs in a functional fashion. So I decided to create &lt;strong&gt;dad joke generator&lt;/strong&gt; via the fantastic and free &lt;a href="https://icanhazdadjoke.com/api"&gt;Dad Joke API&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Even though the feature might be laughable (hah! 😄), it's no joke to implement - at least not for me. We'll have to do HTTP calls, set the correct headers, and deal with something called commands. &lt;/p&gt;

&lt;p&gt;In this article, I'm going to take you through what I did step by step, and try to explain the new concepts I encounter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a good model
&lt;/h2&gt;

&lt;p&gt;I like starting with modeling the state of our application. In this case, we have three possible states - waiting for data, having failed to fetch the data, and successfully fetching the data. We can model that with a regular type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Failure&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I guess we could've created an &lt;code&gt;Idle&lt;/code&gt; state as well, but we're going to fetch a joke initially anyhow, so it won't be a need for that. Speaking of...&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing with commands
&lt;/h2&gt;

&lt;p&gt;The next thing we want to do is intializing our application. It'll be a bit different than we've done previously - instead of just being the initial model, it'll now be a function that returns something called a tuple.&lt;/p&gt;

&lt;p&gt;The type signature looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&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="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a few new things here. First, what's a tuple? In this case, you can think of it as way to return several values from a function. It's &lt;a href="https://dennisreimann.de/articles/elm-data-structures-record-tuple.html"&gt;a bit more complex than that&lt;/a&gt;, but you can think of them as a very light weight data structure of sorts.&lt;/p&gt;

&lt;p&gt;In our case though, we're just returning two things - our initial model, and an initial &lt;code&gt;Cmd&lt;/code&gt;. But what is a &lt;code&gt;Cmd&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Cmd&lt;/code&gt; (or command) is something you want Elm's runtime to do for you. It can be a lot of things, like creating random numbers or accessing browser APIs. Or doing HTTP calls. Once it's resolved somehow, it will return a &lt;code&gt;Msg&lt;/code&gt;, which our &lt;code&gt;update&lt;/code&gt; function will deal with.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're coming from a React background, you can think of this &lt;code&gt;Cmd&lt;/code&gt; argument to our &lt;code&gt;init&lt;/code&gt; function as an action you'd want to run on mount. Kind of like &lt;code&gt;componentDidMount&lt;/code&gt; or &lt;code&gt;useEffect(fn, [])&lt;/code&gt; works!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's write our initializer!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&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="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://icanhazdadjoke.com"&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectString&lt;/span&gt; &lt;span class="kt"&gt;GotJoke&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;We return a tuple with our initial model - &lt;code&gt;Loading&lt;/code&gt;, and a call to the &lt;a href="https://package.elm-lang.org/packages/elm/http/latest/Http#get"&gt;&lt;code&gt;Http.get&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To get this to compile, you need to install the &lt;code&gt;elm/http&lt;/code&gt; package with &lt;code&gt;elm install elm/http&lt;/code&gt; in your terminal, and then imported in your file with &lt;code&gt;import Http&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;Http.get&lt;/code&gt; function accepts a record with two parameters - the &lt;code&gt;url&lt;/code&gt;, and something called &lt;code&gt;expect&lt;/code&gt;. This last one uses another function - &lt;a href="https://package.elm-lang.org/packages/elm/http/latest/Http#expectString"&gt;&lt;code&gt;Http.expectString&lt;/code&gt;&lt;/a&gt;, which tells Elm to parse the response as a string, and then "dispatch" the &lt;code&gt;GotJoke&lt;/code&gt; message with the result.&lt;/p&gt;

&lt;p&gt;But - we haven't specified our messages yet - let's do that next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Messages and results
&lt;/h2&gt;

&lt;p&gt;For now, we only have one possible message to send in our app - namely the "we received a response from the server" value.&lt;/p&gt;

&lt;p&gt;That "we received a response from the server" is wrapped in a &lt;code&gt;Result&lt;/code&gt; type, which can either be an error or the successfully parsed response. We can specify that like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;GotJoke&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I'm no functional programming nut, but if I've understood the introductory blog posts correctly, &lt;code&gt;Result&lt;/code&gt; is what's known as a monad. 😱 Now, after the obligatory panic attacks, I realized monads a just containers for a value that adds some functions for you to use. However, if you're new to functional programming, just close your eyes to the monad part, and just think of &lt;code&gt;Result&lt;/code&gt; as a type that's either &lt;code&gt;Ok&lt;/code&gt; or &lt;code&gt;Err&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the update function
&lt;/h2&gt;

&lt;p&gt;The update function is a bit different this time around as well. The type signature looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like before, the update function receives the message and the initial model, but now it's returning a tuple - two values - &lt;code&gt;(Model, Cmd Msg)&lt;/code&gt;. This feature lets a message trigger a command, if we want to.&lt;/p&gt;

&lt;p&gt;Let's implement it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;GotJoke&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
                &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;joke&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="n"&gt;joke&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="n"&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="kt"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we pattern match the message - even though we just have a single message. By doing it this way, we'll be able to add features without refactoring too much later.&lt;/p&gt;

&lt;p&gt;Inside of the &lt;code&gt;GotJoke&lt;/code&gt; match, we're doing another pattern matching &lt;code&gt;case&lt;/code&gt; to handle the two different cases of the &lt;code&gt;Result&lt;/code&gt; type - an &lt;code&gt;Ok&lt;/code&gt; type with the parsed result, and an &lt;code&gt;Err&lt;/code&gt; type with the error (which we ignore).&lt;/p&gt;

&lt;p&gt;Both the &lt;code&gt;Ok&lt;/code&gt; and the &lt;code&gt;Err&lt;/code&gt; types return a tuple with the &lt;code&gt;Msg&lt;/code&gt; as the first item, and then &lt;code&gt;Cmd.none&lt;/code&gt; as the second. &lt;code&gt;Cmd.none&lt;/code&gt; indicates that we don't want to trigger a new command as a result of this message. This makes sense in our case - because if we got a result, we're done, and if the API call failed, there's no need to try again immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing a view
&lt;/h2&gt;

&lt;p&gt;I'm a front end programmer after all, so the coolest part for me is always going to be implementing the view. Here's what I put together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-align"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elm dad jokes 😎"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
            &lt;span class="kt"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading..."&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="kt"&gt;Failure&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ouch, something went wrong while fetching the stuff over the network"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="n"&gt;theText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;theText&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;Here, I create a containing &lt;code&gt;&amp;lt;div /&amp;gt;&lt;/code&gt;, a heading, and then pattern match our model to create three distinct views based on which state we're in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Namespacing attributes
&lt;/h3&gt;

&lt;p&gt;Notice the &lt;code&gt;A.&lt;/code&gt; in &lt;code&gt;A.style&lt;/code&gt;? Previously, I imported all of the possible attributes into the global namespace with &lt;code&gt;import Html.Attributes exposing (..)&lt;/code&gt;. That turned out to be a bit polluting to my taste. In this app, I'm namespacing them with &lt;code&gt;A&lt;/code&gt;, by changing my import to &lt;code&gt;import Html.Attributes as A&lt;/code&gt;. This way, I don't pollute the global namespace as much, while still keeping the attribute names short when I need to use them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;We've forgotten one step - calling the &lt;code&gt;Browser.sandbox&lt;/code&gt; function. This time, however, since we're introducing commands into the mix, we need to call a different function - &lt;code&gt;Browser.element&lt;/code&gt;. It looks pretty similar, but requires another function - &lt;code&gt;subscriptions&lt;/code&gt;. We're not going to bother with subscriptions this time around, so let's just say we don't have any:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Sub&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Sub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we got all the pieces to call &lt;code&gt;Browser.element&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;strong&gt;should&lt;/strong&gt; be it! Let's run our app to get some laughs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rcm-dqwS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jyz7jd1ics2gvr9ax0k2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rcm-dqwS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jyz7jd1ics2gvr9ax0k2.png" alt="A screen shot of a bunch of HTML where the joke should be"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Argh - I must've missed something - I'm not getting the joke, I'm getting the entire HTML page! This is ridiculous, and not in the way I wanted it to be!&lt;/p&gt;

&lt;p&gt;After reading the &lt;a href="https://icanhazdadjoke.com/api"&gt;API docs&lt;/a&gt;, you have to specify the &lt;code&gt;Accept: text/plain&lt;/code&gt; HTTP header to only get the text. But how do I do that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Try 2 - &lt;code&gt;Http.request&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The original &lt;code&gt;Http.get&lt;/code&gt; function I called earlier didn't support sending headers, but after &lt;em&gt;heading&lt;/em&gt; (hah 😄) over to the &lt;a href="https://package.elm-lang.org/packages/elm/http/latest/Http"&gt;very nice documentation&lt;/a&gt; for the &lt;code&gt;elm/http&lt;/code&gt; package, I came across another function that provided more flexibility - the &lt;code&gt;request&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;After a bit of trial and error, I ended up with changing my &lt;code&gt;init&lt;/code&gt; function to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&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="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET"&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emptyBody&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accept"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://icanhazdadjoke.com"&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectString&lt;/span&gt; &lt;span class="kt"&gt;GotJoke&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tracker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&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;A few more lines of code, but still pretty manageable. After refreshing my page, I got what I had been hoping for:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pQMyJCJx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hcva3sufdzoogr0e8hle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pQMyJCJx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hcva3sufdzoogr0e8hle.png" alt='A screen shot showing the joke "I cut my finger cutting cheese. I know it may be a cheesy story but I feel grate now."'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great success!&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching more jokes!
&lt;/h2&gt;

&lt;p&gt;Even though that joke truly &lt;em&gt;is&lt;/em&gt; a classic, I soon wanted more. So the next feature I wanted to implement was adding a "get a new joke" button! Let's go through the steps I needed to add this new feature.&lt;/p&gt;

&lt;p&gt;First, I added a new type to the &lt;code&gt;Msg&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;GotJoke&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;RequestNewJoke&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now my &lt;code&gt;update&lt;/code&gt; function is broken, since I no longer handle all cases. Let's fix that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;GotJoke&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
                &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="n"&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="kt"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;RequestNewJoke&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetchDadJoke&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we receive a &lt;code&gt;RequestNewJoke&lt;/code&gt; message, we set the state to &lt;code&gt;Loading&lt;/code&gt;, and trigger the command &lt;code&gt;fetchDadJoke&lt;/code&gt;. But where does that last part come from?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fetchDadJoke&lt;/code&gt; command is refactored out from our init function, and is the code that calls the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;fetchDadJoke&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;fetchDadJoke&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET"&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emptyBody&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accept"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://icanhazdadjoke.com"&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectString&lt;/span&gt; &lt;span class="kt"&gt;GotJoke&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tracker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&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="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetchDadJoke&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat, right? I guess I could've refactored out the entire tuple, but it looks pretty nice as is, too.&lt;/p&gt;

&lt;p&gt;Finally, we just need to add some buttons to our UI. I decided to add a retry button in case of errors, as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-align"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elm dad jokes 😎"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
            &lt;span class="kt"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading..."&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="kt"&gt;Failure&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ouch, something went wrong while fetching the stuff over the network"&lt;/span&gt;
                        &lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="kt"&gt;RequestNewJoke&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Try again"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="n"&gt;theText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;theText&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="kt"&gt;RequestNewJoke&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get another joke"&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;And that's it, really! We now have "get a new joke" support as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last thoughts and next moves
&lt;/h2&gt;

&lt;p&gt;I learned a lot building this project, and I hope you did as well with following along. There's quite a few new concepts here, with &lt;code&gt;Result&lt;/code&gt; and &lt;code&gt;Cmd&lt;/code&gt; and what have you. However, it's coming together quite nicely.&lt;/p&gt;

&lt;p&gt;This is the third app I've ever built in Elm, and the syntax is starting to finally feel... "right". I was very skeptical at first, but I think it's growing on me.&lt;/p&gt;

&lt;p&gt;Handling HTTP requests was a breeze, but very few APIs just return simple text strings. So next, I want to integrate with a fully fledged JSON API, so I can try my hands on decoding and encoding JSON. I'm sure it'll be a hoot!&lt;/p&gt;

&lt;p&gt;You can see the entire code for this app in &lt;a href="https://gist.github.com/selbekk/2a9992378f646624818a4fc0cc51443b"&gt;this gist&lt;/a&gt;, and even &lt;a href="https://elm-dad-jokes.netlify.com/"&gt;try it out if you want&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After a bit of struggling, I even made a CodeSandbox of it:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/condescending-frog-8j7x6"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Thanks for following along! If you find any bugs, or have any questions, please feel free to ask in the comments!&lt;/p&gt;

</description>
      <category>elm</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A Year of React - 2019 in Review</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Tue, 31 Dec 2019 08:59:13 +0000</pubDate>
      <link>https://dev.to/selbekk/a-year-of-react-2019-in-review-2pal</link>
      <guid>https://dev.to/selbekk/a-year-of-react-2019-in-review-2pal</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Written in collaboration with &lt;a href="https://twitter.com/caroline_odden" rel="noopener noreferrer"&gt;Caroline Odden&lt;/a&gt; and &lt;a href="https://twitter.com/jonaslochsen?lang=en" rel="noopener noreferrer"&gt;Jonas Løchsen&lt;/a&gt;. This post was first published at &lt;a href="https://blogg.bekk.no/forrigeukes-%C3%A5rskavalkade-2019-c45554088816" rel="noopener noreferrer"&gt;blogg.bekk.no&lt;/a&gt; (in Norwegian), where we also publish weekly React summaries called &lt;code&gt;&amp;lt;ForrigeUke /&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was a &lt;a href="https://www.youtube.com/watch?v=xVlRompc1yE" rel="noopener noreferrer"&gt;great year for Greta&lt;/a&gt;, and a &lt;a href="https://www.bbc.com/news/world-us-canada-39945744" rel="noopener noreferrer"&gt;terrible year for Trump&lt;/a&gt;. But the real winner this year was React, and its amazing community of developers, advocates and regular ol' users. &lt;/p&gt;

&lt;p&gt;There was a lot that happened in 2019. We've spent every Monday night giving you a short summary of all the big and small news stories in this community we all love and cherish. Some of those stories were a bit bigger than the others.&lt;/p&gt;

&lt;p&gt;In this post, we'll go through the year, highlighting some of the biggest new features and news stories of 2019. To finish it off, we've also found the recordings from some of our favorite React conferences!&lt;/p&gt;




&lt;h2&gt;
  
  
  Hooks
&lt;/h2&gt;

&lt;p&gt;After a few months of eager waiting, React 16.8 finally brought the feature we'd been waiting for - Hooks - to a stable release. &lt;/p&gt;

&lt;p&gt;It was at ReactConf 2018 the React Core team let us know they were working on new functionality that was supposed to improve our React quality of life considerably. The proposal was named hooks, and gave us great tools to handle both state and side effects in function components.&lt;/p&gt;

&lt;p&gt;If you didn't catch the initial talk, you can (and should!) see it here:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/V-QO-KO90iQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Oh, and &lt;a href="https://reactjs.org/docs/hooks-intro.html" rel="noopener noreferrer"&gt;here's the introductory blog post, too&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;We also wrote a &lt;a href="https://blogg.bekk.no/et-paradigmeskifte-i-react-a9c6c826b4ed" rel="noopener noreferrer"&gt;post about what we thought about hooks&lt;/a&gt; (in Norwegian), if you want to give that a shot. 🤘&lt;/p&gt;

&lt;h2&gt;
  
  
  React Native gets hooks, too!
&lt;/h2&gt;

&lt;p&gt;The week after Hooks were launched for the web, React Native followed suit. The 0.59 version included full hooks support, and had all of React Native Twitter freaking out 🙌&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1096463521896898562-47" src="https://platform.twitter.com/embed/Tweet.html?id=1096463521896898562"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1096463521896898562-47');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1096463521896898562&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  React Router 5
&lt;/h2&gt;

&lt;p&gt;This was such a great release - completely without breaking changes! Well - almost. The only reason they had to bump their major version was the way they handled their dependencies in &lt;code&gt;react-router-dom&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It might have been in violation with the rules of semantic versioning, but whatever 🤭 &lt;a href="https://reacttraining.com/blog/react-router-v5/" rel="noopener noreferrer"&gt;Here's the release blog post&lt;/a&gt; if you want to read more about it!&lt;/p&gt;

&lt;p&gt;But it wasn't all screw-ups - this version brought React 16 compability, no more &lt;code&gt;&amp;lt;StrictMode /&amp;gt;&lt;/code&gt; warnings, support for an array of paths, and lots more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create React App v3
&lt;/h2&gt;

&lt;p&gt;The third major version of &lt;code&gt;create-react-app&lt;/code&gt; came with a bunch of new cool stuff, including "rules of hooks" eslint support, TypeScript linting and absolute imports. &lt;/p&gt;

&lt;p&gt;You can read the complete changelog &lt;a href="https://github.com/facebook/create-react-app/releases/tag/v3.0.0" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hot Reloading 2.0: Fast Refresh
&lt;/h2&gt;

&lt;p&gt;Hot reloading is simultaneously the best and the worst feature of the React developer experience. It's just amazing to see your components update automatically on save, while keeping the component state. It lets us iterate quicker than on any other platform I know of! At the same time, it has a tendency to not work like half the time, and it can be a nightmare to get working in the first place.&lt;/p&gt;

&lt;p&gt;Most of the reason the developer experience has been both good and bad is that it was a feature implemented in user land. To fix this, the React team has stepped up and implemented a much more stable implementation that works in both React and React Native.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1169687758849400832-851" src="https://platform.twitter.com/embed/Tweet.html?id=1169687758849400832"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1169687758849400832-851');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1169687758849400832&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;It's &lt;a href="https://twitter.com/reactnative/status/1176594928865964032" rel="noopener noreferrer"&gt;already available for React Native&lt;/a&gt;, and support for the web is just weeks away. If you're using Parcel, you can start using it in the newer alpha releases, and Webpack has an open pull request for adding support.&lt;/p&gt;

&lt;p&gt;This means we'll probably get it in &lt;code&gt;create-react-app&lt;/code&gt; as well! We're very excited.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Router and Reach Router join forces
&lt;/h2&gt;

&lt;p&gt;Routing is something most React apps use in some way, and lately there has been two major players out there. React Router has been the defacto choice for a long time, but ever since Gatsby started using the competitor Reach Router, we suddenly have a choice to make when it comes to routing. At least until next year.&lt;/p&gt;

&lt;p&gt;On the Norwegian national day, May 17th, Reach Router king (and React Router founder) Ryan Florence proclaimed that the two libraries are merging into one!&lt;/p&gt;

&lt;p&gt;You can read all the details &lt;a href="https://reacttraining.com/blog/reach-react-router-future/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but in short, we'll see more hooks, less libraries (Reach Router is being deprecated), and a common API moving forward. We've already noticed some of this work with the &lt;a href="https://reacttraining.com/blog/react-router-v5-1/" rel="noopener noreferrer"&gt;new hooks introduced in &lt;code&gt;react-router@5.1.0&lt;/code&gt;&lt;/a&gt;, and we can't want to see what's in store.&lt;/p&gt;

&lt;p&gt;Speaking of mergers - perhaps we'll see more of those moving forward? In the CSS-in-JS world, Styled Components and Emotion is starting to look veeery similar API-wise! 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  New DevTools
&lt;/h2&gt;

&lt;p&gt;After teasing us throughout the year, Brian Vaughn was very proud when he finally revealed &lt;a href="https://reactjs.org/blog/2019/08/15/new-react-devtools.html" rel="noopener noreferrer"&gt;the completely rewritten version of React DevTools&lt;/a&gt; this August. This rewrite brought hooks support, improved performance for large applications and a &lt;strong&gt;much&lt;/strong&gt; better user experience. &lt;/p&gt;

&lt;p&gt;As far as we can tell from his &lt;a href="https://twitter.com/brian_d_vaughn" rel="noopener noreferrer"&gt;Twitter account&lt;/a&gt;, however, Brian Vaughn isn't done implementing new features yet. &lt;a href="https://github.com/facebook/react/blob/master/packages/react-devtools/CHANGELOG.md#430-december-20-2019" rel="noopener noreferrer"&gt;Version 4.3&lt;/a&gt; is already on its way!&lt;/p&gt;

&lt;h2&gt;
  
  
  React Gate
&lt;/h2&gt;

&lt;p&gt;While most of the big names in React were hanging out at React Rally, a pretty nasty Twitter incident happened. What was later known as "React Gate" was a large, distributed argument about the more toxic and racist parts of our community. Racism and social exclusion were discussed in a very vocal and polarizing way, and a lot of people excused themselves from Twitter for an extended period of time. Ugh.&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://dev.to/aryanjnyc/ken-wheeler-and-dan-abramov-deactivate-their-twitter-accounts-302"&gt;great recaps&lt;/a&gt; out there that summarizes the entire debacle, and we wrote about it in two of our &lt;a href="https://blogg.bekk.no/forrigeuke-uke-34-2019-2fe53aa8e3b2" rel="noopener noreferrer"&gt;blog&lt;/a&gt; &lt;a href="https://blogg.bekk.no/forrigeuke-uke-35-2019-9389f04a29ca" rel="noopener noreferrer"&gt;posts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The aftermath wasn't all bad though. On the contrary - some very actionable positive things came from it! The React team has increased their focus on including marginalized groups in tech, and implemented the &lt;a href="https://github.com/facebook/react/blob/master/CODE_OF_CONDUCT.md" rel="noopener noreferrer"&gt;Contributor Covenant Code of Conduct&lt;/a&gt;. Many of the people included in the React Gate episode has later taken on stronger roles in the community, trying to include good folks and shut down the trolls, racists and misogynists. That's what I call a happy ending.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1166364879852359681-974" src="https://platform.twitter.com/embed/Tweet.html?id=1166364879852359681"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1166364879852359681-974');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1166364879852359681&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrent Mode
&lt;/h2&gt;

&lt;p&gt;The big event of this fall was ReactConf in Henderson, Nevada, and it was a really nice one. The biggest news was the introduction of Concurrent Mode - which is now available in the experimental release channel of React. &lt;/p&gt;

&lt;p&gt;Please note, however, that it's still very much experimental, and not available in any stable release. If you're trying to dig into the APIs to be a bit in front when they &lt;em&gt;are&lt;/em&gt; published, however, you should &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html" rel="noopener noreferrer"&gt;dig right in&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To quote &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html" rel="noopener noreferrer"&gt;the extensive documentation&lt;/a&gt;, Concurrent Mode is &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a set of new features that help React apps stay responsive and gracefully adjust to the user’s device capabilities and network speed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sounds wonderful! The React team has provided us with an amazing developer experience as they have iterated on their product, but this feature is a bit different. It's about the end user experience - and making it as smooth as possible. We're really digging that direction!&lt;/p&gt;

&lt;p&gt;Concurrent Mode opens up a new world of possibilities. As the name hints, it lets us render several things concurrently, and even pause rendering certain elements if a higher priority task comes along. All of this plays together to make your app seem as smooth as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hswolff.com/" rel="noopener noreferrer"&gt;Harry Wolff&lt;/a&gt; has written &lt;a href="https://hswolff.com/blog/why-is-react-concurrent-mode-exciting/" rel="noopener noreferrer"&gt;an amazing summary&lt;/a&gt; on why Concurrent Mode is the bees knees, and explains himself with a bunch of great examples.&lt;/p&gt;

&lt;p&gt;He even touches on whether you need to deal with Concurrent Mode. The answer is - as with most new and more advanced React features - no, but it's a huge win for your users if you do. It's a powerful tool that gives you the opportunity to control how your apps is handling asynchronous tasks and rendering your UI - if you have the time and resources, of course.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suspense for data fetching
&lt;/h2&gt;

&lt;p&gt;Since React 16.6, React's new Suspense feature has given you the opportunity to delay rendering of your components while you wait for parts of your application to load, and render a loader instead. With the aforementioned Concurrent Mode, we also get this feature for fetching data, images and basically whatever you want!&lt;/p&gt;

&lt;p&gt;You can read all about in &lt;a href="https://reactjs.org/docs/concurrent-mode-suspense.html" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; (note - this is still experimental!)&lt;/p&gt;

&lt;p&gt;As with anything that's new and shiny, it might be a bit hard to understand how it all fits together. Luckily for us, Maggie Appleton has made an amazing illustrated guide to both Suspense, how it works, and how to use it:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1206644383560478722-312" src="https://platform.twitter.com/embed/Tweet.html?id=1206644383560478722"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1206644383560478722-312');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1206644383560478722&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Another way to understand what problem this new feature solves for us, we also suggest that you have a closer look at this Twitter thread from Dan Abramov. He identifies what the problems with today's solutions are, and pin points how Suspense comes in to save the day.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1193903570078306308-433" src="https://platform.twitter.com/embed/Tweet.html?id=1193903570078306308"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1193903570078306308-433');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1193903570078306308&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Create React App gets templates
&lt;/h2&gt;

&lt;p&gt;In December the 3.3.0 version of the offical React bootstrapping CLI &lt;code&gt;create-react-app&lt;/code&gt; dropped, and it contained a few very cool features.&lt;/p&gt;

&lt;p&gt;First of all, it now supports the concept of custom templates. That is, the files and dependencies that are included when you bootstrap a new project!&lt;/p&gt;

&lt;p&gt;This is a great feature for products like CodeSandbox, since it gives them the opportunity to create much more flexible templates for their users. CodeSandbox even launched what they call their &lt;a href="https://codesandbox.io/post/hello-template-universe-goodbye-project-setup" rel="noopener noreferrer"&gt;Template Universe&lt;/a&gt;, which promises to improve project startup times.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1202580698063941632-900" src="https://platform.twitter.com/embed/Tweet.html?id=1202580698063941632"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1202580698063941632-900');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1202580698063941632&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The other great feature in this new Create React App version is the support for the two new language features in JavaScript - optional chaining and nullish coalescing operators.&lt;/p&gt;

&lt;p&gt;In addition, &lt;code&gt;react-testing-library&lt;/code&gt; is included by default. This wonderful library is a must-have for any project anyways, so I'm glad they decided to include it for all projects. &lt;/p&gt;

&lt;p&gt;For a complete list of new features, we'd refer you to the changelog &lt;a href="https://github.com/facebook/create-react-app/releases/tag/v3.3.0" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redux Style Guide
&lt;/h2&gt;

&lt;p&gt;If you reading this, there's a high probability that you've touched Redux at one point or another. If you haven't - Redux used to be the must-have application state handling library for any new React app.&lt;/p&gt;

&lt;p&gt;Redux has lost much of its glory in the last year, mostly due to improvements in React itself. Many people used Redux as their global store, but with the new Context API and introduction of hooks, solving that problem yourself became almost trivial. In addition, Redux introduced a lot of boiler plate in places where it didn't seem necessary.&lt;/p&gt;

&lt;p&gt;That being said, Redux is still a great tool for complex applications, and - much more important - is probably a part of the tech stack of the legacy app you're stuck maintaining.&lt;/p&gt;

&lt;p&gt;Since Redux probably isn't going anywhere in the foreseeable future - not from the React ecosystem, and not from your app - it's important to use it the best way possible. That's why Mark Erikson and his crew of maintainers has written a very detailed and useful list of recommendations on how you should do things "the Redux way". It includes a set of rules they've split into three sections - essentials, highly recommended, and optional. &lt;/p&gt;

&lt;p&gt;Follow these, and you'll end up with smaller, simpler code with less bugs, and a simpler way to onboard new developers.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1197186583016955904-664" src="https://platform.twitter.com/embed/Tweet.html?id=1197186583016955904"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1197186583016955904-664');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1197186583016955904&amp;amp;theme=dark"
  }



&lt;/p&gt;




&lt;h2&gt;
  
  
  Some of our favorite conferences
&lt;/h2&gt;

&lt;p&gt;In addition to all the new features, libraries and news stories we've stumbled across the last couple of months, we've noticed there has been a ton of React related conferences! We've summarized both &lt;a href="https://blogg.bekk.no/reactconf-2019-en-oppsummering-d7dfcb45dd2f" rel="noopener noreferrer"&gt;React Conf&lt;/a&gt; and &lt;a href="https://blogg.bekk.no/cssconf-eu-jsconf-eu-2019-6261f1f40f0b" rel="noopener noreferrer"&gt;JSConf&lt;/a&gt; (both in Norwegian), but here's a quick overview over all the biggest conferences related to React, and where you can find all the talks. There's no particular order here 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Speaking of conferences - you can find a very complete list of both conferences and meetups related to React on &lt;a href="https://reactjs.org/community/conferences.html" rel="noopener noreferrer"&gt;React's website!&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ReactJS Girls Conf
&lt;/h3&gt;

&lt;p&gt;There was a lot of butts hurt when am all-female speaker React conference was announced. What a silly thing to be pissed off about. The conference was amazing, with incredible talks, exciting speakers and supposedly a really nice experience for those that attended.&lt;/p&gt;

&lt;p&gt;You can see all the talks &lt;a href="https://www.youtube.com/watch?list=PLfrHCOIcmSupF372EGlyi3l4y2R7F8A3q&amp;amp;v=dkl6sYff2C8" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dkl6sYff2C8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  ReactConf
&lt;/h3&gt;

&lt;p&gt;The official React conference had a lot of cool talks, about anything from Suspense to Facebook's internal CSS-in-JS library. I'd especially suggest Sophie Alpert's talk, where she implements a working version of React while live coding it on stage 🤯&lt;/p&gt;

&lt;p&gt;You can see all the talks &lt;a href="https://www.youtube.com/watch?list=PLPxbbTqCLbGHPxZpw4xj_Wwg8-fdNxJRh&amp;amp;v=QnZHO7QvjaM" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/QnZHO7QvjaM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  ReactEurope
&lt;/h3&gt;

&lt;p&gt;As the name implies, this is one of the biggest React conferences in Europe. Among many great talks held, Jared Palmer (the guy behind Formik, TSDX and one half of the Undefined Podcast) did a great talk about the state of React.&lt;/p&gt;

&lt;p&gt;You can see all the talks &lt;a href="https://www.youtube.com/watch?list=PLCC436JpVnK3kcTnPyhcs7QnHK2PKl33D&amp;amp;v=u_0ZMiQZr0k&amp;amp;feature=emb_title" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/u_0ZMiQZr0k"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  React Amsterdam
&lt;/h3&gt;

&lt;p&gt;React Amsterdam has one of the coolest visual identities we've seen, and the content followed suit. Tons of famous React people showed up, including Kent C. Dodds, Max Stoiber and the meme king Mark Dalgleish.&lt;/p&gt;

&lt;p&gt;You can see all the talks &lt;a href="https://www.youtube.com/watch?list=PLNBNS7NRGKMHLTeH4qfD3F320GXfj97kc&amp;amp;v=tO8qHlr6Wqg" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/tO8qHlr6Wqg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  React Advanced
&lt;/h3&gt;

&lt;p&gt;While the US React crowd was partying hard at ReactConf in Nevada, the European scene centered around React Advanced. The &lt;code&gt;r/reactjs&lt;/code&gt; boss Shawn Wang (aka swyx) live coded a hook implementation from stage, and the always entertaining Ken Wheeler (holla) kicked off the keynote with a bit of magic!&lt;/p&gt;

&lt;p&gt;You can see all the talks &lt;a href="https://www.youtube.com/watch?list=PLNBNS7NRGKMH7yfpYQD4TrFV25SMOCIPM&amp;amp;v=t8svxxtUTl8" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/t8svxxtUTl8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  React Rally
&lt;/h3&gt;

&lt;p&gt;Being known as the best React conference to attend must be a good thing for ticket sales. The React Rally was sold out as usual, and it sounds like it was a great time this year, as well as last year. There was some really great talks there this year, but my favorite must've been the 11 year old Revel West's talk "So you think &lt;strong&gt;you're&lt;/strong&gt; a junior dev?" 👶&lt;/p&gt;

&lt;p&gt;You can see all the talks &lt;a href="https://www.youtube.com/watch?list=PLUD4kD-wL_zaXhR4KU1CkUSIzh1TrvnzA&amp;amp;v=XD8UQeYm5Vk" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/XD8UQeYm5Vk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  2019: Reviewed
&lt;/h2&gt;

&lt;p&gt;2019 has been an amazing year for React and its community. The continued focus on improving developer experience is now being matched by an incredible effort to improve the end user experience as well. No matter how you put it - it's all good news.&lt;/p&gt;

&lt;p&gt;The introduction of hooks has really been the change we hoped to see, and it has already simplified a lot of code bases around the world. In addition, hooks has made React so much easier to teach - no more explaining &lt;code&gt;this&lt;/code&gt; and misspelled lifecycle methods.&lt;/p&gt;

&lt;p&gt;Suspense and Concurrent Mode is probably the next couple of big shifts we'll notice in the year to come, when they're finally available in a public release. We've already seen &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html" rel="noopener noreferrer"&gt;how the APIs will look like&lt;/a&gt;, and the work to introduce the larger React ecosystem to its possibilities is going at full steam.&lt;/p&gt;

&lt;p&gt;React Native has received a ton of love in 2019 as well, which has been necessary to fend off the new competition from new frameworks like Flutter and SwiftUI. We're super excited to see new features landing, like Fast Refresh, quicker JavaScript engine (Hermes) and the vastly improved documentation. &lt;/p&gt;

&lt;p&gt;2019 has been a wonderful year for React. We hope and think that we're going to continue that trend in 2020.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Creating a todo app in Elm</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Mon, 30 Dec 2019 12:46:02 +0000</pubDate>
      <link>https://dev.to/selbekk/creating-a-todo-app-in-elm-i3o</link>
      <guid>https://dev.to/selbekk/creating-a-todo-app-in-elm-i3o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I'm going to do something really different - I'm going to learn a new language in the open, and learn by trying to teach what I've learned step by step. The language I'm trying to learn is Elm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the last article in this series, we went through setting up an Elm developer environment, as well as creating a very "hello world"-y counter app.&lt;/p&gt;

&lt;p&gt;In this article, we're going to create something a tiny bit more advanced - &lt;strong&gt;the trusty old todo app&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the model
&lt;/h2&gt;

&lt;p&gt;I think Elm does a lot of things well, but one of my favorite things is that it makes you think about how you're going to model your state. Since we're creating a todo app, it makes sense to start out with modeling a todo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is - a todo is a record (similar to a JavaScript object) with a descriptive text and a completed flag.&lt;/p&gt;

&lt;p&gt;Now, we don't want to handle a single todo, but a list of them. So our model might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;List&lt;/code&gt; in Elm is a linked list implementation of an array, and is &lt;a href="https://package.elm-lang.org/packages/elm/core/latest/List"&gt;well documented&lt;/a&gt;. It's what is created when you write code like &lt;code&gt;list = [1,2,3]&lt;/code&gt;, so it looked like just what I needed.&lt;/p&gt;

&lt;p&gt;Our model is still lacking, though. In order to add todos, we need to keep track of the text in our "add todo" input as well. Therefore, we need to use a record!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're cooking! &lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping out the available actions
&lt;/h2&gt;

&lt;p&gt;So we've been able to create a state model. Next up is creating a list of possible actions that might happen in our application. Let's create a type that enumerates all those possibilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; 
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AddTodo&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;RemoveTodo&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;ToggleTodo&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ChangeInput&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we create four distinct actions - and most accept an argument as well. So the &lt;code&gt;AddTodo&lt;/code&gt; message will accept no arguments, while the &lt;code&gt;RemoveTodo&lt;/code&gt; will accept the index to remove as an argument and so forth. I think this is what you call a parameterized custom type, but don't let that bother you for a second 😄 Just know that the word following the message type is the type of the first argument. If you added a second type after that, it would indicate that the message would expect two arguments, and so forth!&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  type vs type alias
&lt;/h3&gt;

&lt;p&gt;If you paid meticulous attention to the above examples, you noticed that we wrote &lt;code&gt;type alias&lt;/code&gt; when we specified our model, and &lt;code&gt;type&lt;/code&gt; when we specified our message type. Why is that?&lt;/p&gt;

&lt;p&gt;If I've understood the &lt;a href="http://faq.elm-community.org/#what-is-the-difference-between-type-and-type-alias"&gt;FAQ&lt;/a&gt; correctly, a &lt;code&gt;type alias&lt;/code&gt; is  a "shortcut" for a particular type, while a &lt;code&gt;type&lt;/code&gt; is an actual distinct type. I think you could pattern match a type, but not a type alias. We specify the type of functions like &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt; with type aliases.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Writing the business logic
&lt;/h2&gt;

&lt;p&gt;I giggle every time I call the logic in my todo app for "business logic", but I guess it's what it is. No matter what you call it though, we should implement it via the &lt;code&gt;update&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;If you don't remember from the last post of our series, you can think of this method as the "reducer" of a Redux application. It gets called whenever you trigger an action in your app, receives the old state model and expects you to return the updated state model.&lt;/p&gt;

&lt;p&gt;We're going to handle each of the possible messages with a &lt;code&gt;case .. of&lt;/code&gt; expression - which is a way to "pattern match". I still call it a "fancy switch statement". For our app, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;AddTodo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; 
                &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addToList&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputText&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;
                &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;RemoveTodo&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;removeFromList&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;ToggleTodo&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toggleAtIndex&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;ChangeInput&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a tad bit simplified, so let's step through it one case at a time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling AddTodo
&lt;/h3&gt;

&lt;p&gt;First, we handle the &lt;code&gt;AddTodo&lt;/code&gt; message. We use the &lt;code&gt;{ model | something }&lt;/code&gt; syntax to copy the existing model, and then overriding any fields to the right of the &lt;code&gt;|&lt;/code&gt;. In this particular instance, we wouldn't have needed it, since we change the entire state - but by doing it anyways, we make our model easier to extend at a later point in time.&lt;/p&gt;

&lt;p&gt;We get the new &lt;code&gt;todos&lt;/code&gt; value by calling this mystical function &lt;code&gt;addToList&lt;/code&gt;, which is called with the input text and the existing todos list. But how does that function look like?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;addToList&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
&lt;span class="n"&gt;addToList&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;False&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;addToList&lt;/code&gt; accepts a string input text and a list of todos, and returns a new list of todos. We append the old list with a list containing the new todo by using the &lt;code&gt;++&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;In JavaScript, this function would've looked like this:&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;addToList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;todos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&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="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could've inlined this as well, but extracting a function looked a bit cleaner to me 🤷‍♂️&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling RemoveTodo
&lt;/h3&gt;

&lt;p&gt;The next message to handle is &lt;code&gt;RemoveTodo&lt;/code&gt;. We're passed the &lt;code&gt;index&lt;/code&gt; as an argument, and we pass both the index and the existing list as arguments to the &lt;code&gt;removeAtIndex&lt;/code&gt; function. It looks like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;removeFromList&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
&lt;span class="n"&gt;removeFromList&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&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="n"&gt;list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use two list functions called &lt;a href="https://package.elm-lang.org/packages/elm/core/latest/List#take"&gt;&lt;code&gt;List.take&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://package.elm-lang.org/packages/elm/core/latest/List#drop"&gt;&lt;code&gt;List.drop&lt;/code&gt;&lt;/a&gt; to construct two new lists - one that includes all items up to (but not including) the index specified, and one that includes all items from the item after the provided index. Finally, we concatenate the two lists with the &lt;code&gt;++&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;I'm sure there are more clever ways to do this, but that's what I came up with. 🙈&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling ToggleTodo
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ToggleTodo&lt;/code&gt; is pretty similar to the previous one. It calls the &lt;code&gt;toggleAtIndex&lt;/code&gt; function, which looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;toggleAtIndex&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
&lt;span class="n"&gt;toggleAtIndex&lt;/span&gt; &lt;span class="n"&gt;indexToToggle&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indexedMap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;currentIndex&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;indexToToggle&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="k"&gt;else&lt;/span&gt; 
            &lt;span class="n"&gt;todo&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use the &lt;code&gt;indexedMap&lt;/code&gt; list function to loop through all the items, and toggling the completed flag. Note that we're passing an anonymous function to the &lt;code&gt;indexedMap&lt;/code&gt; function - those have to be prefaced by a &lt;code&gt;\&lt;/code&gt; (backslash). Supposedly, the backslash was chosen because it resembles a &lt;code&gt;λ&lt;/code&gt; character - and it denotes a lambda function. It might not make a lot of sense, but it's a nice way to remember to add it! 😄&lt;/p&gt;

&lt;p&gt;The JavaScript version of the same could look like this:&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;toggleAtIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;indexToToggle&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&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;indexToToggle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&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;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling ChangeInput
&lt;/h3&gt;

&lt;p&gt;The last message to handle is the simplest one, really. The &lt;code&gt;ChangeInput&lt;/code&gt; receives the updated input as an argument, and we return the model with an updated &lt;code&gt;inputText&lt;/code&gt; field in response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the view
&lt;/h2&gt;

&lt;p&gt;We've designed a good state model, outlined all possible actions and implemented how they will change the model. Now, all that's left to do is to put all of this on screen!&lt;/p&gt;

&lt;p&gt;As with the counter example in the last article, we implement the &lt;code&gt;view&lt;/code&gt; function. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;onSubmit&lt;/span&gt; &lt;span class="kt"&gt;AddTodo&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Todos in Elm"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onInput&lt;/span&gt; &lt;span class="kt"&gt;ChangeInput&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What do you want to do?"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isEmpty&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The list is clean 🧘‍♀️"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;ol&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indexedMap&lt;/span&gt; &lt;span class="n"&gt;viewTodo&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we create a form with an &lt;code&gt;h1&lt;/code&gt; tag, an input for adding new todos, and a list of todos. If there isn't any todos in your list, we let you know you're done for now.&lt;/p&gt;

&lt;p&gt;We've pulled the "render a todo" logic into its own helper function, &lt;code&gt;viewTodo&lt;/code&gt;. We call it for each of the todos in &lt;code&gt;model.todos&lt;/code&gt; with the &lt;code&gt;List.indexedMap&lt;/code&gt; utility we used earlier. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;viewTodo&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;viewTodo&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;li&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-decoration"&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
                &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line-through"&lt;/span&gt;
             &lt;span class="k"&gt;else&lt;/span&gt;
                &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none"&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="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ToggleTodoCompleted&lt;/span&gt; &lt;span class="n"&gt;index&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="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toggle"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RemoveTodo&lt;/span&gt; &lt;span class="n"&gt;index&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="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Delete"&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;Here, we create a list item with the todo text, and buttons for toggling and removing the list. There's a few things here I thought I'd explain:&lt;/p&gt;

&lt;p&gt;First off, notice that attributes that happen to be a reserved word in Elm is suffixed with &lt;code&gt;_&lt;/code&gt; - like &lt;code&gt;type_&lt;/code&gt; in the buttons.&lt;/p&gt;

&lt;p&gt;Second, notice how you can specify inline styles. It's very verbose, but you could refactor most of that if it's becoming bothersome. For now that's fine.&lt;/p&gt;

&lt;p&gt;Speaking of attributes, I want to do bring your attention to the fact that all HTML attributes are functions! That took me a bit by surprise to begin with, but once you "get it", the syntax makes a lot more sense!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a feature: Filters!
&lt;/h2&gt;

&lt;p&gt;In a typical project, you don't write complete new UIs - you add features to them. So let's add one right now.&lt;/p&gt;

&lt;p&gt;I want to filter out which tasks are done, and what's remaining. Let's start by creating the type definition for a filter, with all its possible state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Filter&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;All&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Completed&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Remaining&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's add a field to our model!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Filter&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; function complains that we haven't specified an initial value for the new &lt;code&gt;filter&lt;/code&gt; value, so let's add that as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;All&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to specify a new message for changing the filter!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;AddTodo&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;RemoveTodo&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;ToggleTodo&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;ChangeInput&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;ChangeFilter&lt;/span&gt; &lt;span class="kt"&gt;Filter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our &lt;code&gt;update&lt;/code&gt; function complains that we haven't handled all possible cases for the &lt;code&gt;Message&lt;/code&gt; type. Implementing it is pretty similar to the &lt;code&gt;ChangeInput&lt;/code&gt; case!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="c1"&gt;-- all the other cases are truncated for brevity&lt;/span&gt;
        &lt;span class="kt"&gt;ChangeFilter&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to change the UI a bit. First, let's create few functions for creating the "select a filter" UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;RadioWithLabelProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Filter&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="n"&gt;viewRadioWithLabel&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;RadioWithLabelProps&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;viewRadioWithLabel&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; 
            &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;radio"&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checked&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ChangeFilter&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt; 
        &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="n"&gt;viewSelectFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Filter&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;viewSelectFilter&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;fieldset&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;legend&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Current filter"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewRadioWithLabel&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;All&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filter"&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;All&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All items"&lt;/span&gt; 
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewRadioWithLabel&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Completed&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filter"&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;Completed&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Completed items"&lt;/span&gt; 
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewRadioWithLabel&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Remaining&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filter"&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;Remaining&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Remaining items"&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;Woah, that was a lot! Let's go through it step by step:&lt;/p&gt;

&lt;p&gt;First, let's look at the &lt;code&gt;viewSelectFilter&lt;/code&gt; function. It accepts the current filter, and returns a fieldset with a legend and three new "nested views" I've named &lt;code&gt;viewRadioWithLabel&lt;/code&gt;. Each of these radio buttons are passed a record with four different arguments.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;viewRadioWithLabel&lt;/code&gt; function is pretty simple, too. It renders a label with an input inside of it, as well as the actual label text. It sets the correct attributes on the &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt; element, and adds an &lt;code&gt;onClick&lt;/code&gt; event listener that triggers the &lt;code&gt;ChangeFilter&lt;/code&gt; message.&lt;/p&gt;

&lt;p&gt;Note that we gave the &lt;code&gt;viewRadioWithLabel&lt;/code&gt; function a single record as its argument (complete with its own type alias), instead of currying four different arguments. I think that makes it much easier to reason about - even if you can't partially apply stuff the same way. &lt;/p&gt;

&lt;p&gt;Finally, we add the &lt;code&gt;viewSelectFilter&lt;/code&gt; to our main &lt;code&gt;view&lt;/code&gt; function, and apply the actual filtering to our list!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;onSubmit&lt;/span&gt; &lt;span class="kt"&gt;AddTodo&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Todos in Elm"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onInput&lt;/span&gt; &lt;span class="kt"&gt;ChangeInput&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What do you want to do?"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewSelectFilter&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isEmpty&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The list is clean 🧘‍♀️"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;ol&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;
                &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;applyFilter&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indexedMap&lt;/span&gt; &lt;span class="n"&gt;viewTodo&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See what's happened where we list out our todos? We're using this new fancy operator &lt;code&gt;|&amp;gt;&lt;/code&gt;, which lets us apply several functions to our list one at a time. &lt;/p&gt;

&lt;p&gt;Let's look at the &lt;code&gt;applyFilter&lt;/code&gt; function as well - it's pretty straight forward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;applyCurrentFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Filter&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;
&lt;span class="n"&gt;applyCurrentFilter&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;All&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;True&lt;/span&gt;

        &lt;span class="kt"&gt;Completed&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt;

        &lt;span class="kt"&gt;Remaining&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! We've now added a completely new feature to our application!&lt;/p&gt;

&lt;h2&gt;
  
  
  So what have we learned?
&lt;/h2&gt;

&lt;p&gt;Elm is starting to show its strengths as we make our applications more complex. There is a lot of lines of code to deal with, but it's all pretty easy once you get used to the syntax.&lt;/p&gt;

&lt;p&gt;Creating complex UIs can be simplified by splitting out view functions as you need them. They're kind of like React components in many ways, but more specialized and less "reusable" by design. I like it!&lt;/p&gt;

&lt;p&gt;While working through this app, I got a lot of assistance from the lovely people on the Elm Slack. I just gotta give it to this community - it's filled with so much love, compassion and helpful people. Thank you for taking the time to explain a lot of functional concepts to a complete beginner!&lt;/p&gt;

&lt;p&gt;So what's next? I think it's about time to look into fetching some data and displaying it somehow. I feel I have gone through enough of the syntax so that I feel comfortable diving into some of the more exciting parts of Elm!&lt;/p&gt;

&lt;p&gt;Did you learn anything from following along? Do you have questions? Or comments on how I could drastically simplify something? Please let me know, and I'll try my best to reply.&lt;/p&gt;

</description>
      <category>elm</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to get started with React in 2020</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Mon, 30 Dec 2019 08:34:24 +0000</pubDate>
      <link>https://dev.to/selbekk/how-to-get-started-with-react-in-2020-4po3</link>
      <guid>https://dev.to/selbekk/how-to-get-started-with-react-in-2020-4po3</guid>
      <description>&lt;p&gt;React is the most popular frontend framework by any standard today. There are in excess of two million developers using it, and a lot has been written about it.&lt;/p&gt;

&lt;p&gt;Even though this is great in many regards, it also comes with downside - it's impossible to figure out where to turn for good content! So with a bit of tongue in cheek - here's yet &lt;strong&gt;another&lt;/strong&gt; article on how you could get started with React. &lt;/p&gt;

&lt;p&gt;What makes this one a bit different, is that I'm in charge of training hundreds of aspiring (or newly hired) developers every year. I've spent a lot of time researching ways to both teach and learn React, and I think I got it down to a science by now. The list is in order, so if you've touched on some of these topics before, feel free to skip ahead.&lt;/p&gt;

&lt;p&gt;So if you're a senior systems engineer that's looking to pick up some frontend skills on the side, or if you're just starting out - this list should help you to get started&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip Redux, Webpack, Babel et al
&lt;/h2&gt;

&lt;p&gt;React is often coupled with a state management tool called Redux. Redux is a &lt;em&gt;great tool&lt;/em&gt; for when you need it, but it's not something you need to know right away. Same goes for other tools you might encounter with React, such as Webpack, Babel, sagas, GraphQL and tons of other ones.&lt;br&gt;
&lt;strong&gt;Skip all of that&lt;/strong&gt;. If you see a tutorial with one of those in the title - Marie Kondo that shit, or save it for later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the React docs from beginning to end
&lt;/h2&gt;

&lt;p&gt;It might sound a bit boring, sure, but it's the best advice you're gonna get. The React documentation has been written, vetted and improved by hundreds of people over the course of half a decade. It's being translated into &lt;a href="https://isreacttranslatedyet.com/"&gt;48 different languages&lt;/a&gt; (!), and is just a fantastic resource in every single way. It's well written, well structured, and is split up into chewable parts you can fly through in a few minutes each.&lt;/p&gt;

&lt;p&gt;Read through its &lt;a href="https://reactjs.org/docs/hello-world.html"&gt;main concepts&lt;/a&gt;, &lt;a href="https://reactjs.org/tutorial/tutorial.html"&gt;cool game tutorial&lt;/a&gt;, and even some of the &lt;a href="https://reactjs.org/docs/accessibility.html"&gt;advanced guides&lt;/a&gt; if you're feeling adventurous.&lt;/p&gt;

&lt;p&gt;There's a huge section on the more "modern" way to use React as well - &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;hooks&lt;/a&gt; - which you should skim through as well. It's definitely the way forward, so spend the time you need to with this material, too.&lt;/p&gt;

&lt;p&gt;Finally, I suggest you get familiar with the &lt;a href="https://reactjs.org/docs/react-api.html"&gt;API reference&lt;/a&gt;. You don't need to go through this one right away, but know that it's there for when you finally need to use one of those exotic APIs you rarely see in the wild.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check out Kent C. Dodds' Beginners Guide to React
&lt;/h2&gt;

&lt;p&gt;If you're into video courses and screen casts, you're going to love this. Honestly, even if you're &lt;em&gt;not&lt;/em&gt; into screen casts, you're going to love this. &lt;/p&gt;

&lt;p&gt;You'll find it for free on &lt;a href="https://egghead.io/courses/the-beginner-s-guide-to-react"&gt;Egghead&lt;/a&gt;, and it's 19 videos totalling a very manageable 77 minutes of content. &lt;/p&gt;

&lt;p&gt;Even seasoned React vets have something to learn in this video series. He'll take you through creating and updating nodes in the DOM manually, doing the same with regular JS-based React, and then showing you how to turn that into that mystical super juice called JSX. And tons of other stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow along with Michael Chan on his holiday adventures
&lt;/h2&gt;

&lt;p&gt;After reading the docs and watching Dodds' beginner guide, you're starting to really have the good feels for this fantastic little framework we all love and enjoy.&lt;/p&gt;

&lt;p&gt;Michael Chan - also known as chantastic - runs the React Podcast, but every holiday season he sits down to do something really cool for the community. This year, he's created a 24 part series, where he's presenting React step by step. &lt;/p&gt;

&lt;p&gt;It's perfect for both experienced devs and for people just starting out. &lt;br&gt;
You can watch it on &lt;a href="https://www.youtube.com/watch?v=YurJDf8JIks&amp;amp;list=PLnc_NxpmOxaP2lgtchapTNNhb_BMFXdgi&amp;amp;index=1"&gt;YouTube&lt;/a&gt; or on &lt;a href="https://dev.to/chantastic/learn-react-in-25-short-lessons-react-holiday-2019-24np"&gt;dev.to&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start building something yourself
&lt;/h2&gt;

&lt;p&gt;So you've read the docs, done the tutorials and seen some incredible videos of smart people introducing increasingly complex topics. Congratulations - you've at the end of this road of teaching. &lt;/p&gt;

&lt;p&gt;The next step in your learning journey shouldn't be more advanced tutorials and courses, it should be building something yourself. Come up with an &lt;a href="https://www.google.com/search?q=app+ideas"&gt;app idea&lt;/a&gt;, and create something at least you'll use!&lt;/p&gt;

&lt;p&gt;This way, you get to get into the &lt;em&gt;real&lt;/em&gt; part of learning React - trying to ship features to actual users in a timely manner. You know how props work - now it's time to learn how they'll work after a couple of weeks of adding features and neglecting debt. It's a lot to learn!&lt;/p&gt;

&lt;h2&gt;
  
  
  Consider a paid course
&lt;/h2&gt;

&lt;p&gt;The React community is lucky in that it has an abundance of free options to get you up to date on the latest and greatest in React. However, some of the most polished content is only available at a premium - as it should be.&lt;/p&gt;

&lt;p&gt;If you're employed, ask your employer to shell out a few bucks for your program of choice. There's a lot to choose from, but here's some of my favorite resources:&lt;/p&gt;

&lt;h3&gt;
  
  
  Egghead
&lt;/h3&gt;

&lt;p&gt;Egghead is an incredible resource, with tons of great, free resources for any skill level. They do have some paid content, though, which can be accessed at a pretty decent price. Check them out at &lt;a href="https://egghead.io/"&gt;egghead.io&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Masters
&lt;/h3&gt;

&lt;p&gt;Frontend Masters is pretty similar to Egghead, but has different content from different authors. You can browse their catalog and find something you're interested in before you shell out for a monthly subscription. Check them out at &lt;a href="https://frontendmasters.com/"&gt;frontendmasters.com&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TestingJavaScript
&lt;/h3&gt;

&lt;p&gt;Not directly React related, but still some of the best money I've spent online. This is Kent C. Dodds' opus to front end testing, which has really kicked off a renewed interest in testing my code for me. If you can afford it, check it out at &lt;a href="https://testingjavascript.com"&gt;testingjavascript.com&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TylerMcGinnis
&lt;/h3&gt;

&lt;p&gt;A bit smaller than the previous platforms, but known for some of the very best content in the React business. Tyler also happens to be a stand up guy, and I'd be happy to give him my moneys. Check out his courses at &lt;a href="https://tylermcginnis.com/courses"&gt;tylermcginnis.com/courses&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wes Bos
&lt;/h3&gt;

&lt;p&gt;Finally, Wes Bos. He was listed as an option for "best resource to learn from" in the State of JS survey this year, so you know he's good. He's got a lot of &lt;a href="https://www.youtube.com/user/wesbos"&gt;free stuff on YouTube&lt;/a&gt;, as well as a long list of paid courses in everything from GraphQL to Markdown. Check them out at &lt;a href="https://wesbos.com/courses/"&gt;wesbos.com/courses&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build your own version of React
&lt;/h2&gt;

&lt;p&gt;As a bonus, I want to share a workshop some colleagues of mine created last year. It's a workshop where you re-implement a basic, yet working version of React and ReactDOM from scratch!&lt;/p&gt;

&lt;p&gt;It was an incredible deep dive into why React works the way it works, and how you can leverage that to your advantage. It's completely free, and will probably be held as an actual workshop at a conference near you in 2019.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sveinpg/build-your-own-react"&gt;Check it out here!&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;So that's it - the definite guide to get started with React development in 2020. At least for now. &lt;/p&gt;

&lt;p&gt;I hope this will get you started on your React journey. If you have any questions, or need a resource to learn a particular type of React development, leave me a comment and I'll try to help you along. This is - after all - for the community. ❤️&lt;/p&gt;

</description>
      <category>react</category>
      <category>learning</category>
    </item>
    <item>
      <title>My first Elm app</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Sun, 29 Dec 2019 23:38:30 +0000</pubDate>
      <link>https://dev.to/selbekk/my-first-elm-app-c70</link>
      <guid>https://dev.to/selbekk/my-first-elm-app-c70</guid>
      <description>&lt;p&gt;I'm going to do something really different - I'm going to learn a new language in the open, and learn by trying to teach what I've learned step by step.&lt;/p&gt;

&lt;p&gt;This might not be the greatest resource you'll find on the web, but I think you'll find it entertainingly honest, at least. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is Elm?
&lt;/h2&gt;

&lt;p&gt;The new language I'm going to learn is Elm. Elm is a functional statically typed language that just happens to compile down to JavaScript! It has "the world's most polite compiler", and a great community. Sounds like a great match to me.&lt;/p&gt;

&lt;p&gt;Like React, it has a virtual DOM implementation to speed it up. It boasts about being &lt;a href="https://elm-lang.org/news/blazing-fast-html-round-two"&gt;really quick&lt;/a&gt;, and it's pretty small as well.&lt;/p&gt;

&lt;p&gt;Speaking of React - Redux was actually based on what's known as the Elm architecture - and it looks pretty similar, too.&lt;/p&gt;

&lt;p&gt;Since it's statically typed, Elm guarantees you &lt;strong&gt;no runtime errors&lt;/strong&gt;, which is a bold thing to claim - but a great thing if it's true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Elm and me?
&lt;/h2&gt;

&lt;p&gt;The company I work for, Bekk, has a great Elm-community as well. The annual &lt;a href="https://osloelmdays.no/"&gt;Oslo Elm Days conference&lt;/a&gt; sprung out from us, and we even employ a core Elm contributor!&lt;/p&gt;

&lt;p&gt;Honestly though, since I've invested so much time and effort in mastering React and becoming sort of a half-known profile in that community, I probably wouldn't have wanted to invest without another reason to egg me on.&lt;/p&gt;

&lt;p&gt;This February, I'm starting a new project with a client that uses Elm for a lot of their frontend apps. In other words - I better start learning. 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's get started!
&lt;/h2&gt;

&lt;p&gt;To get started with a basic first application. To keep it REAL simple, I'll just create a regular old counter app. Because, remember, when you're learning a new framework &lt;em&gt;and&lt;/em&gt; language at once, you need to start out simple.&lt;/p&gt;

&lt;p&gt;First, I head over to the Elm website, and fetch &lt;a href="https://guide.elm-lang.org/install/elm.html"&gt;the correct installer&lt;/a&gt;. Once that's set up, I create a new folder and run &lt;code&gt;elm init&lt;/code&gt; in my terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;counter-app
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;counter-app
&lt;span class="nv"&gt;$ &lt;/span&gt;elm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're then met with a very nice greeting that makes you feel really appreciated. It makes sure you're agreeing to what it's about to do, and then it bootstraps a new project.&lt;/p&gt;

&lt;p&gt;When it's done, you're left with an &lt;code&gt;elm.json&lt;/code&gt; file, and an empty &lt;code&gt;src&lt;/code&gt; folder. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;elm.json&lt;/code&gt; file looks very similar to the trusty old &lt;code&gt;package.json&lt;/code&gt; file we all know.&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source-directories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"src"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"elm-version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.19.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"direct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/browser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"indirect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/json"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.1.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"elm/virtual-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;"1.0.2"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test-dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"direct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"indirect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up VSCode
&lt;/h3&gt;

&lt;p&gt;I use Visual Studio Code for most of my coding, and luckily there's a great Elm plugin available. You'll find it &lt;a href="https://marketplace.visualstudio.com/items?itemName=Elmtooling.elm-ls-vscode"&gt;here&lt;/a&gt;, or by searching the Extensions Marketplace for "Elm". Make sure you don't get the deprecated one!&lt;/p&gt;

&lt;p&gt;Once that's installed, you need to install &lt;code&gt;elm-format&lt;/code&gt; and &lt;code&gt;elm-test&lt;/code&gt; via your preferred package manager as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn global add elm-format elm-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Elm Reactor
&lt;/h3&gt;

&lt;p&gt;Elm comes with its own dev server. You can start it with running &lt;code&gt;elm reactor&lt;/code&gt; in your project, and navigating to &lt;code&gt;localhost:8000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's nice to see all of this being included in the &lt;code&gt;elm&lt;/code&gt; CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start writing Elm!
&lt;/h2&gt;

&lt;p&gt;With all of the setup out of the way, let's start writing some code!&lt;/p&gt;

&lt;p&gt;We create a new file called &lt;code&gt;Main.elm&lt;/code&gt; - and jump right in... but what should we write?&lt;/p&gt;

&lt;p&gt;I started like any sane person does these days, and ran through the &lt;a href="https://guide.elm-lang.org/core_language.html"&gt;official tutorial&lt;/a&gt;. It's a great read, and if you're learning Elm yourself, I suggest you do the same.&lt;/p&gt;

&lt;p&gt;Turns out, in Elm, there's three distinct parts of every "program" - the model, the view and the update function. The model is the state of your application, the view generates the HTML and the update function changes the state based on messages dispatched from the view. Sounds familiar?&lt;/p&gt;

&lt;p&gt;This sounds a lot like Redux actually - and as it turns out, it basically is. Redux is based on the Elm architecture, so if you know Redux, this will look very familiar.&lt;/p&gt;

&lt;h3&gt;
  
  
  The model
&lt;/h3&gt;

&lt;p&gt;Let's go through this first program step by step. First out - we're going to create the model. In our program, it's just the number to display on our counter. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we define the type signature for our model. If you've ever used TypeScript, this will look pretty familiar. Our model is a simple integer.&lt;/p&gt;

&lt;p&gt;Next, we set the initial value to 0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The update function
&lt;/h3&gt;

&lt;p&gt;Now, let's write our "business logic" - the update function. It looks like a Redux reducer of sorts - it accepts the current state and a message (action), and it expects you to return the new updated state.&lt;/p&gt;

&lt;p&gt;We start off by specifying all the actions that can happen in our app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Increment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Decrement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Reset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we can increment, decrement and reset the counter back to zero. Think of these types as actions you can dispatch to your reducer - or messages you can pass to &lt;code&gt;update&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, the &lt;code&gt;update&lt;/code&gt; function itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Increment&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="kt"&gt;Decrement&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="kt"&gt;Reset&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the first like, we specify that the update function accepts a message and the current model value, and then it returns the new model value. Instead of accepting two arguments, the &lt;a href="https://medium.com/javascript-scene/curry-and-function-composition-2c208d774983"&gt;function is curried&lt;/a&gt; so that it accepts one at a time.&lt;/p&gt;

&lt;p&gt;The next line might look a bit weird syntax wise, but it specifies a function &lt;code&gt;update&lt;/code&gt; that accepts two arguments - &lt;code&gt;msg&lt;/code&gt; and &lt;code&gt;model&lt;/code&gt;. We then do something called "&lt;a href="https://www.techopedia.com/definition/8801/pattern-matching"&gt;pattern matching&lt;/a&gt;", which can be understood as a fancy switch statement of sort. We check if the &lt;code&gt;msg&lt;/code&gt; argument is &lt;code&gt;Increment&lt;/code&gt;, &lt;code&gt;Decrement&lt;/code&gt; or &lt;code&gt;Reset&lt;/code&gt;, and in each of these cases, we return the updated value.&lt;/p&gt;

&lt;p&gt;The syntax is a bit weird to me as a JavaScript developer, but I think I'll be able to warm up to it. Objectively speaking, it's clear, concise and easy to read and follow. Note that we also have implicit returns!&lt;/p&gt;

&lt;h3&gt;
  
  
  The view
&lt;/h3&gt;

&lt;p&gt;The view is a function that accepts the model, and returns an Html value with the message type Msg as a parameterized type. If you're not familiar with parameterized types, you can think of them as type arguments (instead of value arguments).&lt;/p&gt;

&lt;p&gt;The type signature looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the function itself looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The counter"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Current count is "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromInt&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="kt"&gt;Decrement&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="kt"&gt;Reset&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reset"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="kt"&gt;Increment&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&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;Do you see what I mean when I say "kind of like React"? This looks very much like &lt;code&gt;React.createElement&lt;/code&gt; with the element to create first, then a list of props, and finally a list of children.&lt;/p&gt;

&lt;p&gt;Here, &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;button&lt;/code&gt; and &lt;code&gt;text&lt;/code&gt; are Elm functions we import (we'll get back to the importing in a bit), which are just called one by one.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;p&lt;/code&gt; function, we even do some string concatenation. Since Elm is a bit strict, we need to change our model from an int to a string to concatenate it.&lt;/p&gt;

&lt;p&gt;Finally, we add the &lt;code&gt;onClick&lt;/code&gt; event listener to all the buttons, and we provide it with the message we want to trigger.&lt;/p&gt;

&lt;p&gt;If you wanted to write the same in React, you'd end up with something like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;The counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Current count is &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decrement&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;button&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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Reset&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increment&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;button&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;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The imports
&lt;/h3&gt;

&lt;p&gt;I didn't mention the imports to begin with, but just like in most other programming languages, you &lt;em&gt;do&lt;/em&gt; need them.&lt;/p&gt;

&lt;p&gt;The syntax is pretty nice, and you'll probably understand it better from looking at the imports we've used so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Browser&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Attributes&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Events&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of the &lt;code&gt;exposing (..)&lt;/code&gt; stuff as named exports, and the other ones as default exports. You can rename imports with &lt;code&gt;as&lt;/code&gt; if you want, just like in JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  The main
&lt;/h3&gt;

&lt;p&gt;The last thing we need now is to kickstart our application somehow - and we do that with the &lt;code&gt;main&lt;/code&gt; function! It's the same as the trusty &lt;code&gt;ReactDOM.render(&amp;lt;App /&amp;gt;, document.querySelector('.app'));&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sandbox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refresh your browser, and you should see a completely unimpressive counter application that adds, subtracts and resets itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What have we learned?
&lt;/h2&gt;

&lt;p&gt;Elm is a pretty cool language for creating modern web apps. It's a statically typed functional language with zero runtime errors and a very nice compiler. &lt;/p&gt;

&lt;p&gt;Each Elm program has a model, a view and an update function - and kind of reminds me of Redux - for good reasons. There's a lot of new scary syntax, but once you try it out, it starts to make sense pretty quickly. &lt;/p&gt;

&lt;p&gt;Creating a simple application was pretty straight forward - but what's next? Let's try to create something a bit more advanced next time.&lt;/p&gt;

</description>
      <category>elm</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introducing bekk.christmas - 12 christmas calendars!</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Mon, 02 Dec 2019 10:36:20 +0000</pubDate>
      <link>https://dev.to/selbekk/introducing-bekk-christmas-2bme</link>
      <guid>https://dev.to/selbekk/introducing-bekk-christmas-2bme</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally posted on our blog - &lt;a href="https://blogg.bekk.no/introducing-bekk-christmas-ad01660ccadf"&gt;blogg.bekk.no&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’re getting in the holiday spirit with an unprecedented push for knowledge sharing and a fun top level domain. &lt;strong&gt;Say ho ho holy moly to our &lt;a href="https://bekk.christmas"&gt;12 Christmas calendars&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR: We’re sharing 12 articles a day until Christmas Eve!
&lt;/h2&gt;

&lt;p&gt;See today’s articles at &lt;a href="https://bekk.christmas"&gt;bekk.christmas&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Say what? 🤶
&lt;/h2&gt;

&lt;p&gt;I’ve always been blown away by the talented people I work with here at Bekk. If I’m ever stuck with some coding challenge, I can always count on receiving a thorough explanation within minutes on our company chat. At every one of our three yearly company gatherings, I’m blown away by the all-Bekk speaker roster, incredible creativity and seamless execution.&lt;/p&gt;

&lt;p&gt;We have been a very visible company at conferences all over the world, with talks about everything from &lt;a href="https://www.youtube.com/watch?v=wySnOo63y_A"&gt;Elm&lt;/a&gt; to &lt;a href="https://www.youtube.com/watch?v=LaVTc4q0ceA"&gt;Continuous Design&lt;/a&gt; 👩‍🎨. We got &lt;a href="https://blogg.bekk.no"&gt;our blog&lt;/a&gt;, where we share stuff like &lt;a href="https://blogg.bekk.no/search?q=forrigeuke"&gt;weekly React newsletters&lt;/a&gt; and how you can battle that &lt;a href="https://blogg.bekk.no/performance-anxiety-and-stage-fright-fe82e814b156"&gt;pesky performance anxiety&lt;/a&gt; 😱. We’ve &lt;a href="https://blogg.bekk.no/pushwagnesizer-en-tverrfaglig-reise-b0a872acbb01"&gt;made art&lt;/a&gt;, &lt;a href="https://blogg.bekk.no/vi-x-internett-5fd410c834db"&gt;designed awards&lt;/a&gt;, and &lt;a href="https://www.facebook.com/gulltaggen/photos/a.10150707164278514/10157979042833514/?type=1&amp;amp;theater"&gt;won them, too&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I invited all of my colleagues to join me in spreading the love and show that our culture of sharing is infused in the DNA of our company — and the response was nothing short of extraordinary.&lt;/p&gt;

&lt;p&gt;We’re incredibly excited, scared, and downright proud to introduce not just one or two, or four, but twelve different Christmas calendars, each covering a topic we’re really, really passionate about.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Twelve different Christmas calendars, each covering a topic we’re really, really passionate about&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ☁️ Cloud Computing at &lt;a href="https://thecloud.christmas"&gt;thecloud.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The rapid evolvement and widespread adoption of the public cloud has made a grand impact on how we write code, how we architect our systems, and even how we think about process. At Bekk we’ve been working with the three major providers for a number of years (sorry, Alibaba Cloud). In this 24-part blog extravaganza we will share some of our knowledge, thoughts and failures! I hope you’re as enthusiastic reading them as we are writing them!&lt;/p&gt;

&lt;h3&gt;
  
  
  👩‍🎤 CSS at &lt;a href="https://css.christmas"&gt;css.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;CSS is becoming more fun every day. New features are added, and browsers are becoming more standards compliant, too! This makes it such a pleasure to work with styling web sites these days. This article will focus on tips and tricks to improve your CSS workflow, and make even nicer looking sites!&lt;/p&gt;

&lt;h3&gt;
  
  
  ➡️ Functional Programming at &lt;a href="https://functional.christmas"&gt;functional.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;FP is the hottest programming paradigm right now, and it’s probably thanks to languages like F#, Kotlin and Elm making it more accessible. We’ve been nerding out over functional programming for ages in Bekk, and we have a lot of cool articles for you to nerd out to, too.&lt;/p&gt;

&lt;h3&gt;
  
  
  ☕️ Java at &lt;a href="//java.christmas"&gt;java.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Bekk has been working on some of the heaviest Java backends our country has to offer. That means we’ve seen some things, and learned a bit as well. This calendar will give you 24 ways to improve your Java-fu in 24 days.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 JavaScript at &lt;a href="https://javascript.christmas"&gt;javascript.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;JavaScript is the most popular language in the world right now, and for good reason. It’s fun, weird and fantastic — all at the same time. This calendar contains a lot of cool tips, and even a few interviews!&lt;/p&gt;

&lt;h3&gt;
  
  
  🔥 Kotlin at &lt;a href="https://kotlin.christmas"&gt;kotlin.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;After Kotlin blew up in 2017, we’ve been using this amazing programming language extensively on a lot of projects. Some places, we even started migrating old Java-code to Kotlin! This calendar is written by some of the greatest Kotlin-programmers in Norway — you have a lot to look forward to!&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 Machine Learning at &lt;a href="https://ml.christmas"&gt;ml.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Each day until Christmas we will give you a brief introduction into a topic related to the exciting field of machine learning and data science. Although there will be some deep dives into statistics and mathematics, everyone should be able to understand the content of this calendar. Whether you are an experienced data scientist, an aspiring novice or just curious about data science — this is the Christmas calendar for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  😍 Open Source at &lt;a href="https://opensource.christmas"&gt;opensource.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We use open source software every single day. A lot of us even contribute back, with bug fixes, documentation tweaks, or even brand new features! This Christmas calendar will be all about open source software, and the lessons we’ve learnt being a part of that for the last two decades.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤔 Product Development at &lt;a href="https://product.christmas"&gt;product.christmas&lt;/a&gt; (in Norwegian)
&lt;/h3&gt;

&lt;p&gt;This one is a bit different. It’s 24 podcast episodes — in Norwegian — about how we do product development here at Bekk. I sure hope you speak Norwegian, because the content is just amazing!&lt;/p&gt;

&lt;p&gt;Available, of course, in your favorite podcast app. Just search for “Kaffeprat hos Bekk”&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚛️ React at &lt;a href="https://react.christmas"&gt;react.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;React is more popular than ever, and — thanks to the innovations of the React team — more capable as well. We’ve written hundreds of React apps the last couple of years, and we dare say we know a thing or to about how to do it right. Look forward to 24 amazing articles in quick succession.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔒 Security at &lt;a href="https://security.christmas"&gt;security.christmas&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A lot of our clients are government agencies, or huge financial organizations. Knowing how to secure their information is critical! Luckily, Bekk has a solid team of security experts that are looking forward to share their knowledge with you for a second consecutive year!&lt;/p&gt;

&lt;h3&gt;
  
  
  👩‍🎨 User Experience at &lt;a href="https://ux.christmas"&gt;ux.christmas&lt;/a&gt; (partly in Norwegian)
&lt;/h3&gt;

&lt;p&gt;What can one expect from a UX advent calendar from Bekk? UX.christmas is a collaborative project where 24 writers have written as many articles, full of industry-relevant tidbits. The “windows” of this advent calendar cover a variety of topics like creativity, storytelling, and product development. Everything from variable fonts and dark patterns (on Friday the 13th of course 👻) to hypothesis testing and digital accessibility.&lt;/p&gt;




&lt;p&gt;Each of these lovely web sites will share a new article every day from December 1st through December 24th. If everything goes well, we’ll have created 288 articles about technology, design and innovation. In 24 days.&lt;/p&gt;

&lt;p&gt;If you’re looking for a daily overview, you can find that at &lt;a href="https://bekk.christmas"&gt;bekk.christmas&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How did we even? 🤯
&lt;/h2&gt;

&lt;p&gt;We’re far from the first ones to create an IT-related Christmas calendar. Advent of Code is a huge international success. In Norway, &lt;a href="https://julekalender.knowit.no/"&gt;knowit&lt;/a&gt; and others has been doing a great job for years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PJRom3h8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ntzyyl3o8d70h982n9q0.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PJRom3h8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ntzyyl3o8d70h982n9q0.JPG" alt="A ton of people showed up for our kickoff"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Bekk Christmas calendar adventure started in 2017, where I bought the domain name React.Christmas on a whim.&lt;/p&gt;

&lt;p&gt;Next year, I got a few of my colleagues to join me in a repeat effort. We wrote a blog post about the entire experience, but long story short, we ended up writing 96 blog posts about React, Elm, JavaScript and IT security.&lt;/p&gt;

&lt;p&gt;This year, we wanted to show off an even wider variety of the incredible people we work with. For those of you who don’t know Bekk, we’re a company of ~450 people, specializing in technology, design and business management. That’s a lot of knowledge not covered by front-end technology and a security calendar!&lt;/p&gt;

&lt;p&gt;To kick us off, Erik Mathisen — our resident copywriter — held an amazing course in how to write well and to keep it short. A lot of the people that signed up as authors (there’s over a 100 of us! 😲) had no previous experience writing articles like these — so we had a lot of learning to do.&lt;/p&gt;

&lt;p&gt;We even live-streamed the talks we held on Twitch to our Trondheim, Norway office — which is also joining the fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s with the artwork? 😍
&lt;/h2&gt;

&lt;p&gt;The artwork featured in our calendars are definitely one of a kind. Well, it’s actually 288 different one of a kinds. Our resident crazy generative artist Kjetil Golid went all out for us, generating a unique piece of art for every day of every calendar. The algorithms are implemented in JavaScript, and based on different Bekk-esque color schemes, and are just amazing.&lt;/p&gt;

&lt;p&gt;You can see more of his artwork on &lt;a href="https://www.instagram.com/kgolid/"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;So there you have it. 288 (or so) articles, mostly written by us. We hope we can inspire you to dive deeper into a few topics, and discover a few new ones outside of your comfort zone. We don’t expect you to read them all, but we hope you find at least a few every day that tickles your fancy.&lt;/p&gt;

&lt;p&gt;Now, &lt;a href="https://bekk.christmas"&gt;get to reading&lt;/a&gt;! Oh — and happy holidays to you all ❤&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>programming</category>
      <category>ux</category>
    </item>
    <item>
      <title>Two media queries you should care about</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Fri, 27 Sep 2019 16:25:07 +0000</pubDate>
      <link>https://dev.to/selbekk/two-media-queries-you-should-care-about-2h5f</link>
      <guid>https://dev.to/selbekk/two-media-queries-you-should-care-about-2h5f</guid>
      <description>&lt;p&gt;CSS is a powerful language. The "media query" feature gives you access to the user's circumstances, device capabilities and preferences.&lt;/p&gt;

&lt;p&gt;That last feature - their display preferences - is an incredibly powerful one. You can react to how people would like their content served!&lt;/p&gt;

&lt;p&gt;This short article will introduce you to two new media queries, which will help make your web sites even better.&lt;/p&gt;

&lt;h2&gt;
  
  
  prefers-reduced-motion
&lt;/h2&gt;

&lt;p&gt;Some users are either sensitive to long and bouncy animations, while other users just don't like them. Either way, there's a very quick way to cater to their wants and needs.&lt;/p&gt;

&lt;p&gt;Simply add the following code to your CSS file:&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="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.my-animated-thing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;animation&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever a user with a preference for reduced motion UIs enters your page, you can turn off particularly intrusive or insistent animations just for them.&lt;/p&gt;

&lt;p&gt;If you want to add a blanket rule to your website, you can address all elements this way:&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="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nl"&gt;animation&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="nl"&gt;transition&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might not want to do this, however - killing all transitions might not be what you want after all. If you have the time and budget, go through all of your motion-adding classes and consider adding a motion-reducing media query to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  prefers-color-scheme
&lt;/h2&gt;

&lt;p&gt;Android, iOS, OSX and Windows now have support for selecting dark mode - a darker version of their general user interface. Wouldn't it be cool if you app could respond to this as well?&lt;/p&gt;

&lt;p&gt;CSS comes to the rescue yet again, with the &lt;code&gt;prefers-color-scheme&lt;/code&gt; media query:&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="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111&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="m"&gt;#eee&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 you're using CSS dynamic properties (also known as CSS variables), you can really add super-powers to your web-site by just changing your entire color scheme in a single swoop:&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="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--primary-background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--primary-text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--contrast-background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--contrast-text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111&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;There are much more media queries you can dip into if you want. You can check them all out &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#Media_features"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's your favorite media query tip?&lt;/p&gt;

</description>
      <category>css</category>
      <category>a11y</category>
    </item>
    <item>
      <title>How to fade in content as it scrolls into view</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Thu, 29 Aug 2019 20:00:51 +0000</pubDate>
      <link>https://dev.to/selbekk/how-to-fade-in-content-as-it-scrolls-into-view-10j4</link>
      <guid>https://dev.to/selbekk/how-to-fade-in-content-as-it-scrolls-into-view-10j4</guid>
      <description>&lt;p&gt;Today, I want to show you a technique for displaying content in a nice and nifty way - by fading it in as it shows up!&lt;/p&gt;

&lt;h2&gt;
  
  
  The fady slidy part 🎚
&lt;/h2&gt;

&lt;p&gt;Let's start with specifying the CSS required. We create two classes - a &lt;code&gt;fade-in-section&lt;/code&gt; base class, and a &lt;code&gt;is-visible&lt;/code&gt; modifier class. You can - of course - name them exactly what you want.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fade-in-section&lt;/code&gt; class should hide our component, while the &lt;code&gt;is-visible&lt;/code&gt; class should show it. We'll use CSS transitions to translate between them. &lt;/p&gt;

&lt;p&gt;The code looks like this:&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;.fade-in-section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20vh&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;0.6s&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;1.2s&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;will-change&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.fade-in-section.is-visible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&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="nl"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;visible&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;Here, we use the &lt;code&gt;transform&lt;/code&gt; property to initially move our container down 1/5th of the viewport (or 20 viewport height units). We also specify an initial opacity of 0.&lt;/p&gt;

&lt;p&gt;By transitioning these two properties, we'll get the effect we're after. We're also transitioning the &lt;code&gt;visibility&lt;/code&gt; property from &lt;code&gt;hidden&lt;/code&gt; to &lt;code&gt;visible&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the effect in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/festive-gould-exvw7"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Looks cool right? Now, how cool would it be if we had this effect whenever we scroll a new content block into the viewport?&lt;/p&gt;

&lt;h2&gt;
  
  
  The showy uppy part 👋
&lt;/h2&gt;

&lt;p&gt;Wouldn't it be nice if an event was triggered when your content was visible? We're going to use the &lt;code&gt;IntersectionObserver&lt;/code&gt; DOM API to implement that behavior.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;IntersectionObserver&lt;/code&gt; API is a really powerful tool for tracking whether something is on-screen, either in part or in full. If you want to dig deep, I suggest you read this &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"&gt;MDN article&lt;/a&gt; on the subject.&lt;/p&gt;

&lt;p&gt;Quickly summarized, however, an intersection observer accepts a DOM node, and calls a callback function whenever it enters (or exits) the viewport. It gives us some positional data, as well as nice-to-have properties like &lt;code&gt;isIntersecting&lt;/code&gt;, which tell us whether something is visible or not.&lt;/p&gt;

&lt;p&gt;We're not digging too deep into the other cool stuff you can do with intersection observers in this article though, we're just implementing a nice "fade in on entry"-feature. And since we're using React, we can write a nice reusable component that we can re-use across our application.&lt;/p&gt;

&lt;p&gt;Here's the code for implementing our component:&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="nx"&gt;FadeInSection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setVisible&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;React&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&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;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIntersecting&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domRef&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="k"&gt;return&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unobserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domRef&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="p"&gt;[]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`fade-in-section &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;domRef&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&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&lt;/span&gt;&lt;span class="err"&gt;&amp;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;And here's a sandbox implementing it:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/beautiful-wiles-k23w5"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you're looking for a copy and paste solution - here you go.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's happening - step by step
&lt;/h3&gt;

&lt;p&gt;If you want to understand what's happening, I've written a step-by-step guide below, that explains what happens.&lt;/p&gt;

&lt;p&gt;First, we call three built in React Hooks - &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useRef&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt;. You can read more about each of these hooks in &lt;a href="https://reactjs.org/docs/hooks-reference.html#basic-hooks"&gt;the documentation&lt;/a&gt;, but in our code we're doing the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a state variable indicating whether the section is visible or not with &lt;code&gt;useState&lt;/code&gt;. We default it to &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a reference to a DOM node with &lt;code&gt;useRef&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create the intersection observer and starting to observe with &lt;code&gt;useEffect&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The setup of the intersection observer might look a bit unfamiliar, but it's pretty simple once you understand what's going on.&lt;/p&gt;

&lt;p&gt;First, we create a new instance of the IntersectionObserver class. We pass in a callback function, which will be called every time any DOM element registered to this observer changes its "status" (i.e. whenever you scroll, zoom or new stuff comes on screen). Then, we tell the observer instance to observe our DOM node with &lt;code&gt;observer.observe(domRef.current)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before we're done, however, we need to clean up a bit - we need to remove the intersection listener from our DOM node whenever we unmount it! Luckily, we can return a cleanup function from &lt;code&gt;useEffect&lt;/code&gt;, which will do this for us.&lt;/p&gt;

&lt;p&gt;That's what we're doing at the end of our &lt;code&gt;useEffect&lt;/code&gt; implementation - we return a function that calls the &lt;code&gt;unobserve&lt;/code&gt; method of our observer. (Thanks to &lt;a href="https://dev.to/dance2die"&gt;Sung Kim&lt;/a&gt; for pointing this out to me in the comment section!)&lt;/p&gt;

&lt;p&gt;The callback we pass into our observer is called with a list of entry objects - one for each time the &lt;code&gt;observer.observe&lt;/code&gt; method is called. Since we're only calling it once, we can assume the list will only ever contain a single element.&lt;/p&gt;

&lt;p&gt;We update the &lt;code&gt;isVisible&lt;/code&gt; state variable by calling its setter - the &lt;code&gt;setVisible&lt;/code&gt; function - with the value of &lt;code&gt;entry.isIntersecting&lt;/code&gt;. We can further optimize this by only calling it once - so as to not re-hide stuff we've already seen.&lt;/p&gt;

&lt;p&gt;We finish off our code by attaching our DOM ref to the actual DOM - by passing it as the &lt;code&gt;ref&lt;/code&gt; prop to our &lt;code&gt;&amp;lt;div /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can then use our new component like this:&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;FadeInSection&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This will fade in&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;FadeInSection&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;FadeInSection&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This will fade in too!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;FadeInSection&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;FadeInSection&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;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"yoda.png"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fade in, this will"&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;FadeInSection&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;And that's how you make content fade in as you scroll into the view!&lt;/p&gt;

&lt;p&gt;I'd love to see how you achieve the same effect in different ways - or if there's any way to optimize the code I've written - in the comments.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  A final note on accessibility
&lt;/h2&gt;

&lt;p&gt;Although animation might look cool, some people have physical issues with them. In their case, animations is detrimental to the user experience. Luckily, there's a special media query you can implement for those users - namely &lt;code&gt;prefers-reduced-motion&lt;/code&gt;. You can (and should!) read more about it in &lt;a href="https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/"&gt;this CSS Tricks article&lt;/a&gt; on the subject.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to stop your spinner from jumping in React</title>
      <dc:creator>selbekk</dc:creator>
      <pubDate>Thu, 22 Aug 2019 10:17:06 +0000</pubDate>
      <link>https://dev.to/selbekk/how-to-stop-your-spinner-from-jumping-in-react-5cmp</link>
      <guid>https://dev.to/selbekk/how-to-stop-your-spinner-from-jumping-in-react-5cmp</guid>
      <description>&lt;p&gt;Sometimes, when loading data in a web app, it happens in this waterfall-y approach. First, you fetch some auth data, then some user data, and finally the data required to build your view.&lt;/p&gt;

&lt;p&gt;This can often lead to different spinners being rendered in the same place, leading to the following user experience:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/jumping-spinners-yubc0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;See how that spinner kind of "jumps" back to start every time the text changes? &lt;em&gt;I hate that!&lt;/em&gt; Granted, this issue will probably disappear once we can use &lt;a href="https://css-tricks.com/reacts-experimental-suspense-api-will-rock-for-fallback-ui-during-data-fetches/" rel="noopener noreferrer"&gt;Suspense&lt;/a&gt; for everything - but until then I'd love to fix this for our customers.&lt;/p&gt;

&lt;p&gt;This "jump" happens because a new spinner is mounted to our DOM, and the CSS animation is started anew. &lt;/p&gt;

&lt;p&gt;A few weeks ago, React Native DOM author &lt;a href="https://twitter.com/vincentriemer" rel="noopener noreferrer"&gt;Vincent Reimer&lt;/a&gt; posted this little demo:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1160670658512052224-806" src="https://platform.twitter.com/embed/Tweet.html?id=1160670658512052224"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1160670658512052224-806');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1160670658512052224&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I was amazed! 🤩 Is this even a possibility? How would you even do that?&lt;/p&gt;

&lt;p&gt;After staring in bewilderment for a few minutes, I started digging into how this could be achieved. And as it turns out, it's a pretty simple trick!&lt;/p&gt;

&lt;h2&gt;
  
  
  How to sync your spinners
&lt;/h2&gt;

&lt;p&gt;The moving parts of spinners are typically implemented with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations" rel="noopener noreferrer"&gt;CSS animations&lt;/a&gt;. That's what I did in the example above, at least. And that animation API is pretty powerful. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;animation-delay&lt;/code&gt; property is typically used to orchestrate CSS animations, or stagger them one after another (first fade in, then slide into place, for example). But as it turns out, it can be used to rewind the animation progress as well - by &lt;strong&gt;passing it negative values&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Since we know how long our spinner animation loop is, we can use negative &lt;code&gt;animation-delay&lt;/code&gt; values to "move" the animation to the correct spot when our spinner mounts.&lt;/p&gt;

&lt;p&gt;Given the following CSS:&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;keyframe&lt;/span&gt; &lt;span class="nt"&gt;spin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;360deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.spinner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000ms&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt; &lt;span class="n"&gt;spin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--spinner-delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* visual spinner styles omitted */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can set the animation delay when our spinner component mounts:&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;Spinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;mountTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;mountDelay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mountTime&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;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spinner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
      &lt;span class="nx"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please wait&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--spinner-delay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mountDelay&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Here, we use React's &lt;code&gt;useRef&lt;/code&gt; hook to save the point in time our &lt;code&gt;Spinner&lt;/code&gt; component mounted. We then calculate the amount of milliseconds to "rewind" our spinner animation, and make that value negative.&lt;/p&gt;

&lt;p&gt;Finally, we pass down the &lt;code&gt;--spinner-delay&lt;/code&gt; CSS custom property via a style prop.&lt;/p&gt;

&lt;p&gt;Here's the result:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/non-jumping-spinners-ojkjr"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  More detail please
&lt;/h2&gt;

&lt;p&gt;If you want a step-by-step on what happens here? No worries, here it is. In excruciating detail. 🙈&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;mountTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;Date.now()&lt;/code&gt; returns the amount of milliseconds from January 1st, 1970 (&lt;a href="https://stackoverflow.com/questions/2533563/why-are-dates-calculated-from-january-1st-1970/2533567" rel="noopener noreferrer"&gt;see here&lt;/a&gt; for a deeper dive into why that is). We're going to use that number as a baseline for where our animation will be when it mounts.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;React.useRef&lt;/code&gt; hook lets you save an arbitrary value without triggering a re-render. It's perfect for saving stuff like our "mount time". You can see &lt;a href="https://reactjs.org/docs/hooks-reference.html#useref" rel="noopener noreferrer"&gt;the documentation&lt;/a&gt;) for more details about this function.&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;mountDelay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mountTime&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;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;mountDelay&lt;/code&gt; constant is the actual number of milliseconds we're going to "rewind" our animation. The number &lt;code&gt;1000&lt;/code&gt; must match the amount of milliseconds the animation runs for - so if your spinner spins slower or quicker than the one in this example, you will have to adjust this number.&lt;/p&gt;

&lt;p&gt;We're accessing the value calculated in &lt;code&gt;mountTime&lt;/code&gt; by accessing the &lt;code&gt;current&lt;/code&gt; property of the &lt;code&gt;mountDelay&lt;/code&gt; ref. This is how React refs are structured.&lt;/p&gt;

&lt;p&gt;We're using the modulo operator &lt;code&gt;%&lt;/code&gt; to figure out how many milliseconds out into our animation we are. If you're not familiar with the &lt;code&gt;%&lt;/code&gt; operator, that's fine. If you do &lt;code&gt;1123 % 1000&lt;/code&gt;, you get 123. If you do &lt;code&gt;15 % 15&lt;/code&gt;, you get 0. You can read more about it &lt;a href="https://riptutorial.com/javascript/example/760/remainder---modulus----" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Finally, we're negating the number, since we want a negative delay value to pass into the &lt;code&gt;animation-delay&lt;/code&gt; property.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--spinner-delay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mountDelay&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did you know you can pass in CSS custom properties (formerly known as CSS variables) to your classes via the &lt;code&gt;style&lt;/code&gt; prop? Yeah, me neither! Turns out, that's actually a pretty nifty technique to pass dynamic values to our CSS. Note that we're suffixing our millisecond value with &lt;code&gt;ms&lt;/code&gt; before passing it in. &lt;/p&gt;

&lt;p&gt;You can read more about custom properties on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;.&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;keyframe&lt;/span&gt; &lt;span class="nt"&gt;spin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;360deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.spinner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000ms&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt; &lt;span class="n"&gt;spin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--spinner-delay&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;In our CSS, we specify our animation via the &lt;code&gt;animation&lt;/code&gt; property, and then we specify the &lt;code&gt;animation-delay&lt;/code&gt; value separately. You could do this in the &lt;code&gt;animation&lt;/code&gt; declaration as well, but this is a bit more readable to me.&lt;/p&gt;

&lt;p&gt;And that's it!&lt;/p&gt;

&lt;p&gt;I hope you use this technique to improve your spinners, and share it with your friends. Thanks for reading 👋&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>css</category>
      <category>ux</category>
    </item>
  </channel>
</rss>
