<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>hooks &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<atom:link href="https://jessewarden.com/tag/hooks/feed" rel="self" type="application/rss+xml" />
	<link>https://jessewarden.com</link>
	<description>Software &#124; Fitness &#124; Gaming</description>
	<lastBuildDate>Sun, 17 Feb 2019 20:51:02 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://jessewarden.com/wp-content/uploads/2016/08/cropped-Lambda2-32x32.png</url>
	<title>hooks &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<link>https://jessewarden.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Easier Asynchronous State Modelling in React Redux or Hooks</title>
		<link>https://jessewarden.com/2019/02/easier-asynchronous-state-modelling-in-react-redux-or-hooks.html</link>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sun, 17 Feb 2019 19:52:28 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[adt]]></category>
		<category><![CDATA[algebriacdatatype]]></category>
		<category><![CDATA[folktale]]></category>
		<category><![CDATA[hooks]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[react]]></category>
		<category><![CDATA[redux]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=5796</guid>

					<description><![CDATA[Introduction Modelling state for asynchronous actions in React using Redux via thunks or sagas is verbose. It requires a lot of code. It also is easy to accidentally miss flipping one of the values and result in a wrong state that your UI then shows the wrong thing. Thankfully there are ways to use Algebraic [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>Modelling state for asynchronous actions in <a href="https://reactjs.org/">React</a> using <a href="https://redux.js.org/">Redux</a> via <a href="https://github.com/reduxjs/redux-thunk">thunks</a> or <a href="https://github.com/redux-saga/redux-saga">sagas</a> is  verbose.  It requires a lot of code. It also is easy to accidentally miss flipping one of the values and result in a wrong state that your UI then shows the wrong thing. Thankfully there are ways to use Algebraic Data Types to model this state that results in less code in your reducers, whether in Redux or Hooks&#8217; <a href="https://reactjs.org/docs/hooks-reference.html#usereducer">useReducer</a>, as well as in your components. Below we&#8217;ll show the 3 problems modelling using Objects can cause and how to solve them using ADT&#8217;s.</p>



<p>All <a href="https://github.com/JesterXL/react-redux-async-types">code shown below is on Github</a>. The <code>master</code>branch has the <code>Object</code> way of modelling, and the <code>types</code> branch has the ADT solutions.</p>



<p>Most of the post below is based on prior art from <a href="https://www.youtube.com/watch?v=IcgmSRJHu_8">Making Impossible States Impossible by Richard Feldman</a>, and <a href="https://www.youtube.com/watch?v=6TDKHGtAxeg">Solving the Boolean Identity Crisis by Jeremy Fairbank</a>. Like Redux, stolen from <a href="https://elm-lang.org/">Elm</a>.</p>



<span id="more-5796"></span>



<h2 class="wp-block-heading">Defining The Problem</h2>



<p>When you load data from a remote data source, most likely from a REST based HTTP server, you&#8217;ll have 3 states: loading, error, and success. This means loading the data, the data failed to load because of an error, and the data successfully loaded.</p>



<h3 class="wp-block-heading">Loading State</h3>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="1024" height="583" src="http://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.13-PM-1-1024x583.png" alt="" class="wp-image-5798" srcset="https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.13-PM-1-1024x583.png 1024w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.13-PM-1-300x171.png 300w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.13-PM-1-768x437.png 768w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.13-PM-1.png 1441w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Loading state</figcaption></figure>



<h3 class="wp-block-heading">Error State</h3>



<figure class="wp-block-image"><img decoding="async" width="1024" height="583" src="http://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.20-PM-1024x583.png" alt="" class="wp-image-5799" srcset="https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.20-PM-1024x583.png 1024w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.20-PM-300x171.png 300w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.20-PM-768x437.png 768w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.47.20-PM.png 1441w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Error state</figcaption></figure>



<h3 class="wp-block-heading">Success State</h3>



<figure class="wp-block-image"><img decoding="async" width="1024" height="623" src="http://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.46.57-PM-1024x623.png" alt="" class="wp-image-5800" srcset="https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.46.57-PM-1024x623.png 1024w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.46.57-PM-300x183.png 300w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.46.57-PM-768x467.png 768w, https://jessewarden.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-17-at-12.46.57-PM.png 1441w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Success state.</figcaption></figure>



<p>To slowly model the above into a <a href="http://jessewarden.com/2012/07/finite-state-machines-in-game-development.html">finite state machine</a>, you start with loading state in your reducer so your component knows &#8220;if loading, show the loading state, else don&#8217;t&#8221;. You default it to <code>true</code>so your UI will be assumed to be waiting to load data.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>
}</code></span></pre>


<p>When the data loads, you can set the <code>isLoading</code>to <code>false</code> and put your data on the <code>Object</code>:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
  , <span class="hljs-attr">foods</span>: &#91;...]
}</code></span></pre>


<p>However, for errors, you need to indicate that it IS an error, so you add another <code>Boolean</code>:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
  , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
  , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
}</code></span></pre>


<p>For logging and for the UI, you need to show this <code>Error</code> so you then add it as well:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
  , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
  , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
  , <span class="hljs-attr">error</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'b00m b00m <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a3.png" alt="💣" class="wp-smiley" style="height: 1em; max-height: 1em;" />'</span>)
}</code></span></pre>


<h3 class="wp-block-heading">Problem #1: Lots of Verbose, Duplicate Code</h3>



<p>Every single asynchronous action in your application has about the same 3 states and 4 properties in an Object to represent it. You then go to represent it in a basic reducer function. When using Redux or <code>useReducer</code>, you use reducer functions, which is the name for the function you put in a <code>reduce</code>function, like <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce">Array.prototype.reduce</a> or <a href="https://lodash.com/docs/4.17.11#reduce">Lodash&#8217; reduce</a>. Below, &#8220;foods&#8221; is our reducer function:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> foods = <span class="hljs-function">(<span class="hljs-params">state=defaultState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span>(action.type) {
    <span class="hljs-keyword">case</span> LOAD_FOODS:
      <span class="hljs-keyword">return</span> {
        ...state
        , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>
      }
    <span class="hljs-keyword">case</span> LOAD_FOODS_FAILURE:
      <span class="hljs-keyword">return</span> {
        ...state
        , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
        , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
        , <span class="hljs-attr">error</span>: action.error
      }
    <span class="hljs-keyword">case</span> LOAD_FOODS_SUCCESS:
      <span class="hljs-keyword">return</span> {
        ...state
        , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
        , <span class="hljs-attr">foods</span>: action.foods
  }
}</code></span></pre>


<p>However, either through TDD, manual testing, or unit tests, you start to find out basic problems with your reducer function, and state machines in general: the transitions between states can lead to impossible states&#8230; and your UI freaks out&#8230; or doesn&#8217;t and hides the weirdness.</p>



<p>If we go from loading to error, that&#8217;s fine, our state is:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> state = {
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
  , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
  , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
  , <span class="hljs-attr">error</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(...)
}</code></span></pre>


<h3 class="wp-block-heading">Problem #2: Impossible States</h3>



<p>But if we then retry, we&#8217;ll go from loading to success which results in:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> state = {
  <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
  , <span class="hljs-attr">foods</span>: &#91;...]
  , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
  , <span class="hljs-attr">error</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(...)
}</code></span></pre>


<p>Wat. How do we have <code>foods</code>and an <code>isError</code> set to true!?</p>



<h3 class="wp-block-heading">Problem #3: Incorrect and Unclear UI Behavior</h3>



<p>You know something&#8217;s wrong when your UI shows an error even though the Network Panel in Chrome shows a status code 200 for the request and the JSON data all looks good:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> FoodsView = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
    useEffect(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        props.loadFoodsThunk()
    }, &#91;])

    <span class="hljs-keyword">if</span>(props.foods.isLoading) {
        <span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Loading</span> /&gt;</span></span>)
    }
    <span class="hljs-comment">// WHY IS IT STOPPING HERE FOR A SUCCESS!?!<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f620.png" alt="😠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span>
    <span class="hljs-keyword">if</span>(props.foods.isError) {
        <span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Failed</span> <span class="hljs-attr">error</span>=<span class="hljs-string">{props.foods.error}/</span>&gt;</span></span>)
    }

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FoodsList</span> <span class="hljs-attr">foods</span>=<span class="hljs-string">{props.foods.foods}</span> <span class="hljs-attr">calories</span>=<span class="hljs-string">{props.calories}</span> <span class="hljs-attr">addFood</span>=<span class="hljs-string">{props.addFood}</span> <span class="hljs-attr">removeFood</span>=<span class="hljs-string">{props.removeFood}</span> /&gt;</span></span>
    )
}</code></span></pre>


<p>You realize you need to be super explicit about state transitions to ensure you don&#8217;t accidentally end up in an impossible state like the above where you have a success and error at the same time. We&#8217;ll make our reducer way more verbose to ensure all the unit tests pass:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> foods = <span class="hljs-function">(<span class="hljs-params">state=defaultState, action</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span>(action.type) {
        <span class="hljs-keyword">case</span> LOAD_FOODS:
            <span class="hljs-keyword">return</span> {
                ...state
                , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>
                , <span class="hljs-attr">isError</span>: <span class="hljs-literal">false</span>
                , <span class="hljs-attr">error</span>: <span class="hljs-literal">undefined</span>
                , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
            }
        <span class="hljs-keyword">case</span> LOAD_FOODS_FAILURE:
            <span class="hljs-keyword">return</span> {
                ...state
                , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
                , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
                , <span class="hljs-attr">error</span>: action.error
                , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
            }
        <span class="hljs-keyword">case</span> LOAD_FOODS_SUCCESS:
            <span class="hljs-keyword">return</span> {
                ...state
                , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
                , <span class="hljs-attr">isError</span>: <span class="hljs-literal">false</span>
                , <span class="hljs-attr">error</span>: <span class="hljs-literal">undefined</span>
                , <span class="hljs-attr">foods</span>: action.foods
            }
        <span class="hljs-attr">default</span>:
            <span class="hljs-keyword">return</span> state
    }
}</code></span></pre>


<p>While cool in that it&#8217;s the same pattern, it can be monotonous to duplicate this easily in each of your async reducers that need it without copy pasta. Worse, this is just 3 states. In some cases, especially in Enterprise applications where you&#8217;re dealing with legacy code or services that just go down a lot because of technical debt or high traffic, you could be in an &#8220;unstable&#8221; state, similar to the <a href="https://martinfowler.com/bliki/CircuitBreaker.html">Circuit Breaker Pattern</a>. That&#8217;s ok and expected, but you can start to see how your Object grows, and it&#8217;s not always so obvious what state transition bugs could occur, so you make your reducer even more verbose.</p>



<p>In an Object Oriented (OOP) code base, we&#8217;d just wrap this in a class with methods to ensure safe transitions. This abstraction makes it easier to read and we can test the class in isolation. That won&#8217;t help the UI part above, though.</p>



<p>So what do we do in a Functional Codebase?</p>



<h2 class="wp-block-heading">Solving The Problems</h2>



<p>To prevent the duplicated code, ensure you can&#8217;t reach impossible states in an FP way, and make your UI more clear and easier to debug, we&#8217;ll use an Algebraic Data Type, sometimes called a Tagged Union, provided by <a href="https://folktale.origamitower.com/api/v2.3.0/en/folktale.adt.union.union.union.html">Folktale</a>. There are other libraries you can use for this such as <a href="https://github.com/evilsoft/crocks">Crocs</a> and <a href="https://github.com/sanctuary-js/sanctuary">Sanctuary</a>. If you want to learn more, I have a video <a rel="noreferrer noopener" href="https://www.youtube.com/watch?v=OghJR3BP0Ns" target="_blank">Fun With Folktale</a> which covers the basics at <a rel="noreferrer noopener" href="https://youtu.be/OghJR3BP0Ns?t=1615" target="_blank">26:55</a>.</p>



<p>First, <code>npm install folktale</code> or <code>yarn add folktale</code> and let&#8217;s import it:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">import</span> { union } <span class="hljs-keyword">from</span> <span class="hljs-string">'folktale/adt/union'</span></code></span></pre>


<p>We have a default initial state that looks like:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> defaultState = {
    <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>
    , <span class="hljs-attr">error</span>: <span class="hljs-literal">undefined</span>
    , <span class="hljs-attr">isError</span>: <span class="hljs-literal">false</span>
    , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
}</code></span></pre>


<p>Let&#8217;s model that same data structure with a type in Folktale:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> FoodsState = union(<span class="hljs-string">'FoodsState'</span>, {
    LoadingFoods() { <span class="hljs-keyword">return</span> {} }
    , FoodsLoaded(foods) { <span class="hljs-keyword">return</span> { foods } }
    , FoodsError(error) { <span class="hljs-keyword">return</span> { error } }
})</code></span></pre>


<p>Instead of 4 un-related, yet related, properties, we can see our 3 states clearly:</p>



<ol class="wp-block-list"><li><strong>LoadingFoods</strong>: loading the food data</li><li><strong>FoodsLoaded</strong>: the list is loaded, and the <code>Array</code> is inside</li><li><strong>FoodsError</strong>: the list failed to load, and the <code>Error</code> is inside </li></ol>



<p>We can leave them in <code>FoodsState</code>, but let&#8217;s destructure them so it&#8217;s less to type:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> { LoadingFoods, FoodsLoaded, FoodsError } = FoodsState</code></span></pre>


<h3 class="wp-block-heading">Solving Problem #2: Many States is Now One State at a Time</h3>



<p>Since there are 3 different Objects, we solve problem #2: You can only be in 1 state at a time. Let&#8217;s update our reducer&#8217;s function signature that has the defaultState:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> foods = <span class="hljs-function">(<span class="hljs-params">state=defaultState, action</span>) =&gt;</span> {</code></span></pre>


<p>To show this:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> foods = <span class="hljs-function">(<span class="hljs-params">state=LoadingFoods(</span>), <span class="hljs-params">action</span>) =&gt;</span> {</code></span></pre>


<p>Way more clear than &#8220;defaultState&#8221; or &#8220;initialState&#8221;; it says exactly right there what state we&#8217;re starting in: Loading. Notice it can&#8217;t magically be <code>FoodsLoaded</code> or <code>FoodsError</code>at the same time like it could in our <code>Object</code>.</p>



<h3 class="wp-block-heading">Solving Problem #1: Verbose Code is Now Less Code</h3>



<p>Let&#8217;s take our massive reducer function switch statement:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">switch</span>(action.type) {
    <span class="hljs-keyword">case</span> LOAD_FOODS:
        <span class="hljs-keyword">return</span> {
            ...state
            , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>
            , <span class="hljs-attr">isError</span>: <span class="hljs-literal">false</span>
            , <span class="hljs-attr">error</span>: <span class="hljs-literal">undefined</span>
            , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
        }
    <span class="hljs-keyword">case</span> LOAD_FOODS_FAILURE:
        <span class="hljs-keyword">return</span> {
            ...state
            , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
            , <span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
            , <span class="hljs-attr">error</span>: action.error
            , <span class="hljs-attr">foods</span>: <span class="hljs-literal">undefined</span>
        }
    <span class="hljs-keyword">case</span> LOAD_FOODS_SUCCESS:
        <span class="hljs-keyword">return</span> {
            ...state
            , <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span>
            , <span class="hljs-attr">isError</span>: <span class="hljs-literal">false</span>
            , <span class="hljs-attr">error</span>: <span class="hljs-literal">undefined</span>
            , <span class="hljs-attr">foods</span>: action.foods
        }
    <span class="hljs-attr">default</span>:
        <span class="hljs-keyword">return</span> state
}</code></span></pre>


<p>&#8230; and use our union types to write less code AND still ensure only 1 state at a time:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-keyword">switch</span>(action.type) {
    <span class="hljs-keyword">case</span> LOAD_FOODS:
        <span class="hljs-keyword">return</span> LoadingFoods()
    <span class="hljs-keyword">case</span> LOAD_FOODS_FAILURE:
        <span class="hljs-keyword">return</span> FoodsError(action.error)
    <span class="hljs-keyword">case</span> LOAD_FOODS_SUCCESS:
        <span class="hljs-keyword">return</span> FoodsLoaded(action.foods)
    <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> state
}</code></span></pre>


<p>Who&#8217;s your buddy? WHO&#8217;S YOUR BUDDY!?</p>



<p>If the <code>action.type</code>is loading, cool, we&#8217;re loading. If the type is failure, we return a failed type and put the error in side. Lastly, if we&#8217;re successful, we return a success with our data inside. 28 lines to 10.</p>



<h3 class="wp-block-heading">Solving Problem #3: Unclear UI Showing Wrong State to More Clear, Deterministic, and Easier to Debug</h3>



<p>Lastly, our UI can more clearly represent this state. Instead of the imperative, abort early and render based on our guess at what the <code>Object</code> means:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> FoodsView = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
    useEffect(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        props.loadFoodsThunk()
    }, &#91;])

    <span class="hljs-keyword">if</span>(props.foods.isLoading) {
        <span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Loading</span> /&gt;</span></span>)
    }
    
    <span class="hljs-keyword">if</span>(props.foods.isError) {
        <span class="hljs-keyword">return</span> (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Failed</span> <span class="hljs-attr">error</span>=<span class="hljs-string">{props.foods.error}/</span>&gt;</span></span>)
    }

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FoodsList</span> <span class="hljs-attr">foods</span>=<span class="hljs-string">{props.foods.foods}</span> <span class="hljs-attr">calories</span>=<span class="hljs-string">{props.calories}</span> <span class="hljs-attr">addFood</span>=<span class="hljs-string">{props.addFood}</span> <span class="hljs-attr">removeFood</span>=<span class="hljs-string">{props.removeFood}</span> /&gt;</span></span>
    )
}</code></span></pre>


<p>We can instead run a pure function against the type using <code>matchWith</code>:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> FoodsView = <span class="hljs-function"><span class="hljs-params">props</span> =&gt;</span> {
    useEffect(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        props.loadFoodsThunk()
    }, &#91;])

    <span class="hljs-keyword">return</span> props.foods.matchWith({
        <span class="hljs-attr">LoadingFoods</span>: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span>
            (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Loading</span> /&gt;</span></span>)
        , <span class="hljs-attr">FoodsError</span>: <span class="hljs-function">(<span class="hljs-params">{ error }</span>) =&gt;</span>
            (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Failed</span> <span class="hljs-attr">error</span>=<span class="hljs-string">{error}</span> /&gt;</span></span>)
        , <span class="hljs-attr">FoodsLoaded</span>: <span class="hljs-function">(<span class="hljs-params">{ foods }</span>) =&gt;</span>
            (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FoodsList</span> <span class="hljs-attr">foods</span>=<span class="hljs-string">{foods}</span> <span class="hljs-attr">calories</span>=<span class="hljs-string">{props.calories}</span> <span class="hljs-attr">addFood</span>=<span class="hljs-string">{props.addFood}</span> <span class="hljs-attr">removeFood</span>=<span class="hljs-string">{props.removeFood}</span> /&gt;</span></span>)
    })
}</code></span></pre>


<p>No need to inspect different <code>Booleans</code>and guess you did it in the right order, or have things break even if you did, you now have VERY clearly named states to match against using a pure function.</p>



<h2 class="wp-block-heading">Conclusions</h2>



<p>Modelling asynchronous data in Redux or the <code>useReducer</code> React Hook can  result in states that are impossible, yet your UI goes there by accident. This results in verbose reducers that are a pain to maintain as the amount of <code>fetch</code> calls in your application grows. Unless you have good tests, it also will sometimes result in UI bugs if you accidentally don&#8217;t model a state just right with all the <code>Boolean</code> flags set to the correct values.</p>



<p>Using ADT&#8217;s, or tagged unions, we can ensure impossible states are impossible to get to, we can significantly reduce how much reducer code we write, and our UI render code becomes more clear, testable, and debuggable.</p>



<h3 class="wp-block-heading">Et tu, Action Creators?</h3>



<p>And before you ask, sadly no, you cannot use them for Action Creators. Redux and various Redux libraries expect Action Creators to be pure Objects, and the <code>type</code> property to a <code>String</code>. I suppose you could create your own middleware, thus drastically reducing your reducer size and they&#8217;d become map functions vs. reducer functions. But at that point, you&#8217;re better off using Elm, heh!</p>



<h3 class="wp-block-heading">Can Strong Typing Help Here?</h3>



<p>On that note, be aware that TypeScript and Flow, currently, cannot detect if you&#8217;ve handled all match cases. For example, if you do this in your UI:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">return</span> props.foods.matchWith({
    <span class="hljs-attr">LoadingFoods</span>: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span>
        (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Loading</span> /&gt;</span></span>)
    , <span class="hljs-attr">FoodsError</span>: <span class="hljs-function">(<span class="hljs-params">{ error }</span>) =&gt;</span>
        (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Failed</span> <span class="hljs-attr">error</span>=<span class="hljs-string">{error}</span> /&gt;</span></span>)
    , <span class="hljs-attr">FoodsLoaed</span>: <span class="hljs-function">(<span class="hljs-params">{ foods }</span>) =&gt;</span>
        (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FoodsList</span> <span class="hljs-attr">foods</span>=<span class="hljs-string">{foods}</span> <span class="hljs-attr">calories</span>=<span class="hljs-string">{props.calories}</span> <span class="hljs-attr">addFood</span>=<span class="hljs-string">{props.addFood}</span> <span class="hljs-attr">removeFood</span>=<span class="hljs-string">{props.removeFood}</span> /&gt;</span></span>)
})</code></span></pre>


<p>Notice we misspelled <code>FoodsLoaded</code>to <code>FoodsLoaed</code>. The compiler in Elm would catch that and not compile, but <a href="https://www.typescriptlang.org/">TypeScript</a> and <a href="https://flow.org/">Flow</a> will not. This will result in a runtime exception. The <a href="https://github.com/tc39/proposal-pattern-matching">pattern matching proposal for JavaScript</a> is at Stage 1 at the time of this writing so until that solidifies, if you&#8217;re a TypeScript fan, they have <a href="https://pattern-matching-with-typescript.alabor.me/">better ways of doing pattern matching the TypeScript way</a> which&#8217;ll give you ADT&#8217;s + strong typing guarantees. It&#8217;s too verbose for my taste, though.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>D2W and Roundtable with Joel Hooks &#038; Nick Joyce &#8211; JXLTV Episode #006</title>
		<link>https://jessewarden.com/2010/02/roundtable-with-joel-hooks-nick-joyce-jxltv-episode-006.html</link>
					<comments>https://jessewarden.com/2010/02/roundtable-with-joel-hooks-nick-joyce-jxltv-episode-006.html#comments</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Fri, 26 Feb 2010 04:10:33 +0000</pubDate>
				<category><![CDATA[jxltv]]></category>
		<category><![CDATA[d2w]]></category>
		<category><![CDATA[dee]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[hooks]]></category>
		<category><![CDATA[joel]]></category>
		<category><![CDATA[joyce]]></category>
		<category><![CDATA[nick]]></category>
		<category><![CDATA[pyamf]]></category>
		<category><![CDATA[pycon]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[robotlegs]]></category>
		<category><![CDATA[sadler]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=2087</guid>

					<description><![CDATA[Announcements: D2W Conference Dee Sadler &#8211; Twitter &#124; Site RIA Radio &#8211; Episode 8: Jesse Warden DebugWindow v2 &#8211; Log window for Flex apps References: PyCon &#8211; Atlanta Python Conference Joel Hooks &#8211; Twitter &#124; Blog Robotlegs &#8211; MVCS Framework for AS3 and Flex Nick Joyce on Twitter PyAMF &#8211; AMF support for Python Universal [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="viddler_cb438f21" name="viddler_cb438f21">
<pre style="border: 0px; margin: 0px;">
<object type="video/mp4" data="http://jessewarden.com/archives/jxltv/jxltv-episode-006.jpg" width="460" height="258">
			<param name="controller" value="false" />
			<param name="src" value="http://jessewarden.com/archives/jxltv/jxltv-episode-006.jpg" />
			<param name="href" value="http://jessewarden.com/archives/jxltv/jxltv-episode-006-iphone.mp4" />
			<param name="target" value="myself" />
				<img decoding="async" src="http://jessewarden.com/archives/jxltv/jxltv-episode-006.jpg" alt="JXL TV Episode 6"></img>
		</object>
</pre>
</div>
<pre style="border: 0px; margin: 0px;"><script type="text/javascript">

var flashvars = {};
var params = {
	allowScriptAccess: "always",
	allowFullScreen: "true"
};
var attributes = {
  id: "viddler_cb438f21",
  name: "viddler_cb438f21"
};

swfobject.embedSWF("http://www.viddler.com/player/cb438f21/", "viddler_cb438f21", "437", "287", "9.0.0","http://www.jessewarden.com/expressInstall.swf", flashvars, params, attributes);

</script></pre>
<p><span id="more-2087"></span><br />
<b>Announcements:</b></p>
<ul>
<li><a href="http://www.d2wc.com/default/index.cfm">D2W Conference</a></li>
<li>Dee Sadler &#8211; <a href="http://twitter.com/deesadler">Twitter</a> | <a href="http://aboxofpixels.com/">Site</a></li>
<li><a href="http://www.insideria.com/2010/02/ria-radio---episode-7-jesse-wa.html">RIA Radio &#8211; Episode 8: Jesse Warden</a></li>
<li><a href="http://jessewarden.com/2010/02/debug-window-v2-simple-flex-debug-window.html">DebugWindow v2 &#8211; Log window for Flex apps</a></li>
</ul>
<p><b>References:</b></p>
<ul>
<li><a href="http://us.pycon.org/2010/about/">PyCon &#8211; Atlanta Python Conference</a></li>
<li>Joel Hooks &#8211; <a href="http://twitter.com/jhooks">Twitter</a> | <a href="http://joelhooks.com/">Blog</a></li>
<li><a href="http://robotlegs.org/">Robotlegs &#8211; MVCS Framework for AS3 and Flex</a></li>
<li><a href="http://twitter.com/nick_joyce">Nick Joyce</a> on Twitter</li>
<li><a href="http://pyamf.org/">PyAMF</a> &#8211; AMF support for Python</li>
<li><a href="http://universalmind.com/">Universal Mind</a> &#8211; RIA Consulting Firm</a></li>
<li><a href="http://jessewarden.com/2007/12/mix-n-mash-2k7-bill-gates-web-blend-and-silverlight.html" title="Mix n Mash 2007 - Bill Gates n Bloggers by jesterxl, on Flickr"><img loading="lazy" decoding="async" src="http://farm3.static.flickr.com/2276/2092951645_934a0ece66_m.jpg" width="240" height="160" alt="Mix n Mash 2007 - Bill Gates n Bloggers" /></a></li>
<p><b>Beer</b> &#8211; <a href="http://beeradvocate.com/beer/profile/418/3434">Milk Stout</a> by <a href="http://www.lefthandbrewing.com/">Left Hand Brewing Company</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2010/02/roundtable-with-joel-hooks-nick-joyce-jxltv-episode-006.html/feed</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		<enclosure url="http://jessewarden.com/archives/jxltv/jxltv-episode-006-iphone.mp4" length="279814530" type="video/mp4" />

			</item>
	</channel>
</rss>
