<?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: Francesco Sardo</title>
    <description>The latest articles on DEV Community by Francesco Sardo (@frankiesardo).</description>
    <link>https://dev.to/frankiesardo</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%2F554038%2Fd218c74b-5c7c-45b2-a24c-fc19395001a8.jpeg</url>
      <title>DEV Community: Francesco Sardo</title>
      <link>https://dev.to/frankiesardo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/frankiesardo"/>
    <language>en</language>
    <item>
      <title>Share state using custom hooks</title>
      <dc:creator>Francesco Sardo</dc:creator>
      <pubDate>Tue, 17 Aug 2021 14:04:25 +0000</pubDate>
      <link>https://dev.to/frankiesardo/share-state-using-custom-hooks-5245</link>
      <guid>https://dev.to/frankiesardo/share-state-using-custom-hooks-5245</guid>
      <description>&lt;p&gt;Many articles have been written about React state management strategies for React, and yes, this is yet another one of them. But rather than talking about a new library and how everyone should adopt it, I want to talk about two different philosophical approach to state: centralised vs decentralised.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decentralised state paradigm
&lt;/h2&gt;

&lt;p&gt;Decentralised state has been the battery-included solution since the first version of React. Class components can edit local state to trigger a re-render, and functional components can accomplish the same with the &lt;code&gt;useState&lt;/code&gt; hook. &lt;/p&gt;

&lt;p&gt;Local state is very intuitive to manipulate because it sits near the component that uses it for display and side effects, it's allocated when needed, and disappears when the component is unmounted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The centralised state paradigm
&lt;/h2&gt;

&lt;p&gt;Keeping all mutable state in one place is an approach championed by Elm, ClojureScript and Redux: a single data structure (usually a tree) contains all the state needed to render your React application. When a branch of that tree changes state, the relevant components in your React hierarchy re-render displaying the new information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjh6fvhqttth686rqcml8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjh6fvhqttth686rqcml8.png" alt="Screenshot 2021-08-11 at 21.27.07"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A single point of reference for the entire app state is a very neat idea and feels like a natural evolution on top of React itself: React abstracts DOM changes with components, the app state abstracts component changes with a big JSON value.&lt;/p&gt;

&lt;p&gt;Since all changes are represented with data, the logic that transitions the app through different states is very easy to express and to test: it's just a function &lt;code&gt;f(currentState, event) =&amp;gt; newState&lt;/code&gt;. It's also easy to generate many valid UI screens by mocking the app state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpnb4kvtblrwjkhsw9u7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpnb4kvtblrwjkhsw9u7.png" alt="Screenshot 2021-08-15 at 21.45.26"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://github.com/frankiesardo/speccards" rel="noopener noreferrer"&gt;speccards&lt;/a&gt; generates random valid UI states based on a spec&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems with decentralised state
&lt;/h2&gt;

&lt;p&gt;Local state becomes problematic when two components need to watch and act on the same state. Think about a simple currency converter where the user can edit either currency text input.&lt;/p&gt;

&lt;p&gt;In this case the naive solution is to "lift the state up" to the closest parent and give all children callback functions to manipulate the state. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc4r26cibamtwqw1982l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc4r26cibamtwqw1982l.png" alt="Screenshot 2021-08-15 at 21.49.56"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;em&gt;&lt;a href="https://reactjs.org/docs/lifting-state-up.html" rel="noopener noreferrer"&gt;Lifting State Up&lt;/a&gt; in vanilla React&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This rarely scales for bigger applications, so something like &lt;a href="https://recoiljs.org/" rel="noopener noreferrer"&gt;Recoil&lt;/a&gt; might be needed for more powerful sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems with centralised state
&lt;/h2&gt;

&lt;p&gt;You can easily get started with centralised state with the &lt;code&gt;useReducer&lt;/code&gt; hook and keeping all state inside the top &lt;code&gt;&amp;lt;App/&amp;gt;&lt;/code&gt; component, passing down state as &lt;code&gt;props&lt;/code&gt; wherever they are needed. What you'll find soon enough, though, is that components far away from the root will require forever more information, and you'll have to drill all the props through the tree until they reach the correct component.&lt;/p&gt;

&lt;p&gt;This, again, doesn't scale for large applications, so some forms of &lt;code&gt;subscriptions&lt;/code&gt; to parts of the state tree are required to keep the app performant and easy to extend. You might need something like the &lt;a href="https://react-redux.js.org/api/hooks#useselector" rel="noopener noreferrer"&gt;hook version of Redux&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How the two compare in terms of Developer Experience
&lt;/h2&gt;

&lt;p&gt;I have always been a huge advocate of the centralised approach. It appealed to me because of its functional purity and how it made accessing and manipulate state much easier in the pre-hook era. I have since changed my mind, and I'd like to explain why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Centralised state gives you the &lt;em&gt;illusion&lt;/em&gt; of correctness&lt;/strong&gt;. The state neatly transitions from one pure value to another thanks little functions that encapsulate your business logic. You might even have tests for those functions that say something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

- When button is clicked
- Set the loading indicator to true
- Clear the input field
- Send an http call to the server


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Except that when you actually run the app, the behaviour is not what you expected. The problem is that your logic is far removed from your UI components, and while sound and correct in principle, it doesn't play well with your render code. It might be because the state has a different shape, but more often that not, it's because the intended values are not added to the state at the right time.&lt;/p&gt;

&lt;p&gt;Modelling your app as a succession of states works well when you deal mostly with synchronous interactions, like a game, but starts to show its limit with more asynchronous behaviour, like fetching new data over the internet. It's easy to describe how the data changes but not &lt;strong&gt;how the data gets there in the first place&lt;/strong&gt;. So you might end up with an infinite spinner because an action has not been triggered or received at the right time (e.g. when the user navigated to a new screen).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8684vlq0qyi46rpal4a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8684vlq0qyi46rpal4a.gif" alt="1_8NJgObmgEVhNWVt3poeTaA"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Annoying when that happens eh?&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Colocating state, effects and ui
&lt;/h2&gt;

&lt;p&gt;Advocates of the centralised state approach have a great argument: UI should not care about state management and side effects, it should just care about displaying values. Extract the logic somewhere else and test it.&lt;/p&gt;

&lt;p&gt;While poignant in principle, this doesn't work well in practice. The reverse tends to be true: it's useful to think about components as fragments of the screen with a well defined behaviour. They can trigger actions, listen to events and manipulate state that affects other components.&lt;/p&gt;

&lt;p&gt;Over the last year I've been writing components with complex behaviour, fully expecting things to break and knowing I'll be refactoring them with some centralised solution. To my surprise, this nontrivial, large app, kept on getting bigger and accumulating new features without getting significantly more complex. I would even say it scaled in ways that Redux, ClojureScript or Elm apps haven't been in the past, even with less "formal proofs" (tests, types) of correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  A hook with a name
&lt;/h2&gt;

&lt;p&gt;Consider this component&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;function&lt;/span&gt; &lt;span class="nf"&gt;ItemList&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;auth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUser&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;itemsPerPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePreferences&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;searchQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSearch&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;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useItems&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;itemsPerPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchQuery&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;To me it clearly communicates its dependencies (inputs) and how it uses them for display. Moreover, these inputs are not just static data but a combination of state and effect.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useUser&lt;/code&gt; returns the current user info if logged in, otherwise it triggers an authentication flow&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;usePreferences&lt;/code&gt; gets saved data asynchronously from IndexedDB&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useSearch&lt;/code&gt; extracts the query parameters in the current url&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useItems&lt;/code&gt; ties everything together, getting the items server side and caching them for future uses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When each one of these dependencies change (the url parameters, or the local storage being cleared, or the user token expiring) the hooks will take care of re-fetching and re-rendering the component.&lt;/p&gt;

&lt;p&gt;Custom hooks that encapsulate caching are also a great way to share data between components: user, preferences, and remote data all reside in-memory and only need to be fetched once. The first component that uses the hook triggers the async behaviour and all the other components can subsequently access it free of charge.&lt;/p&gt;

&lt;p&gt;You can even go one step beyond and wrap this behaviour in a hook itself:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useSearchItems&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;auth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUser&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;itemsPerPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePreferences&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;searchQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSearch&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;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useItems&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;itemsPerPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchQuery&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So you can have the same list of items in two different part of the application (say: the list itself and a Count indicator somewhere else).&lt;/p&gt;

&lt;p&gt;Hooks can be seen as a dependency graph: what they "require" (other hook calls) and what they provide (the returned value). Editing this graph is really easy if you stick with React hooks and don't go outside of it with centralised state management.&lt;/p&gt;

&lt;p&gt;This patterns composes really well and scales as you create new components. Need another components to access this list? It's a one line change. Don't need access to that data anymore? Removing the hook or the component itself means it's not fetched in that screen anymore.&lt;/p&gt;

&lt;p&gt;State (what's cached), behaviour (which effects load and invalidate the data) and UI can be closely linked together again, so they evolve organically together with your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  There's an app for that
&lt;/h2&gt;

&lt;p&gt;Writing hooks manually that load, cache and invalidate it's obviously time consuming, and there's no need to do that when there are great libraries out there already.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react-query.tanstack.com/" rel="noopener noreferrer"&gt;React Query&lt;/a&gt; obviously stands out with its incredible DX. It works with http, graphql and any asynchronous behaviour really (e.g. IndexedDB).&lt;/p&gt;

&lt;p&gt;This library alone gives you so much leverage it might be the only solution you need. If we're talking about state sharing without asynchronous behaviour, then Recoil might be a good addition too. If you're using custom hooks with a descriptive name, it won't really matter which library you use underneath.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c1"&gt;// Prefer this&lt;/span&gt;&lt;br&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;repos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRepos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;// To this&lt;/span&gt;&lt;br&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;repos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;repoData&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&lt;a href="https://api.github.com/repos/tannerlinsley/react" rel="noopener noreferrer"&gt;https://api.github.com/repos/tannerlinsley/react&lt;/a&gt; query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  A real world example&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;It's always best to show how ideas are implemented in practice rather than just talking about them so I've created &lt;a href="//firebuzz.app"&gt;firebuzz.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnivmbecfyn416zdcqd0j.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnivmbecfyn416zdcqd0j.jpeg" alt="WhatsApp Image 2021-08-01 at 19.57.27"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Players can buzz to answer questions and receive points&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can browse the source code (and it particular the &lt;code&gt;hooks&lt;/code&gt; folder) over here &lt;a href="https://github.com/frankiesardo/firebuzz" rel="noopener noreferrer"&gt;https://github.com/frankiesardo/firebuzz&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Steal these ideas (from ClojureScript) right now</title>
      <dc:creator>Francesco Sardo</dc:creator>
      <pubDate>Tue, 05 Jan 2021 14:41:54 +0000</pubDate>
      <link>https://dev.to/frankiesardo/copying-some-good-ideas-from-clojurescript-2md2</link>
      <guid>https://dev.to/frankiesardo/copying-some-good-ideas-from-clojurescript-2md2</guid>
      <description>&lt;p&gt;Clojure(Script) is a delightful language and learning it will make you look at familiar concepts in a completely different way. Its emphasis on data transformations gives you immense clarity in understanding a problem: code syntax fades away when you think about how the data flows through the system.&lt;/p&gt;

&lt;p&gt;I recently started working on vanilla React projects, and it surprised me that some hard-earned lessons in the cljs ecosystem that I take for granted have not reached the wider React community. ClojureScript and React have been working together really well since the beginning, and cljs devs have scaled very complex UIs thanks to some tricks that I think will benefit everyone growing a React application.&lt;/p&gt;

&lt;p&gt;Let's have a look at an example shall we, it will be easier to explain the concepts with some code running in front of your eyes. You want to create a simple component that fetches the Github repos for a given username. You open up your editor and quickly come up with something like this (well, probably looking prettier than this)&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/learn-you-a-cljs-1-4pbpd?view=editor"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;What's the problem with it? Well, nothing really. A strong selling point of React is how well it adapts to different styles, whether functional or more object oriented. Here we just want to throw something together and seeing that it works, and the problem is simple enough that we don't need anything more complex that a few stateful components.&lt;br&gt;
But let's imagine for a moment that we're working on a bigger app, and, while still using the same example for simplicity's sake, we want to scale things up a bit. Let's hear what advice we can take from cljs.&lt;/p&gt;
&lt;h2&gt;
  
  
  🗃️ (1) Keep the state all in one place
&lt;/h2&gt;

&lt;p&gt;That is probably the first thing you're going to hear from any Clojure developer. Stateful components are notoriously harder to understand, debug and scale, precisely because they hide complexity inside them.&lt;/p&gt;

&lt;p&gt;Here's David Nolen, author of the hugely influential library om.&lt;/p&gt;

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

&lt;p&gt;And if you're not convinced yet, please do watch &lt;a href="https://www.youtube.com/watch?v=-6BsiVyC1kM"&gt;Rich Hickey's The value of values&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagining the application state as one big "memory database" is what allowed concepts like &lt;strong&gt;Pure Components&lt;/strong&gt;, &lt;strong&gt;Global Undo&lt;/strong&gt;, and &lt;strong&gt;Time Travel Debugging&lt;/strong&gt; to become popular. &lt;br&gt;
Centralising app states greatly simplifies things. Think about it: would  you prefer to connect to one database or a hundred different databases?&lt;/p&gt;

&lt;p&gt;We also start to see the idea of your components being nothing more than a function that maps data to UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Component(data) =&amp;gt; UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In many React circles this idea quickly became popular and that's how Redux came to be (inspired by Flux and The Elm Architecture) and is now part of React itself with the &lt;code&gt;useReducer&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;We can rewrite our simple example like so:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/learn-you-a-cljs-2-fjod0?view=editor"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This also has the benefit of making the UI more modular: we can extract a &lt;code&gt;Form&lt;/code&gt; component from the previous example because it can just use and update the state independently of other components.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌶 (2) Make your app Hot Reloadable
&lt;/h2&gt;

&lt;p&gt;Years ago I used to build Android Apps and the OS had this mechanism called &lt;a href="https://developer.android.com/reference/android/app/Activity#onSaveInstanceState(android.os.Bundle)"&gt;&lt;code&gt;onSaveInstanceState()&lt;/code&gt;&lt;/a&gt; where Android asks every little piece of stateful UI: "hey, what's your current state?" so that it can save it temporarily when your app is killed by the system. It is quite an annoying thing to implement. I even &lt;a href="https://github.com/frankiesardo/icepick"&gt;wrote a library for it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagine how easy it would be for Android if the state of your app was all in one place. Implementing save &amp;amp; restore would be one line of code. And that's why ClojureScript had the first and still the best experience of Hot Module Reload that anyone has ever seen.&lt;/p&gt;

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

&lt;p&gt;Hot Module Reload is not just about updating a function or two: it's about &lt;strong&gt;changing the UI behaviour but preserving its state&lt;/strong&gt;. Watch the talk and see what happens when Bruce Hauman changes the game logic as he plays it: if it doesn't blow your mind, nothing ever will. Oh, and once you recover from the shock go ahead and watch &lt;a href="https://www.youtube.com/watch?v=PUv66718DII"&gt;Bret Victor's Inventing on principle&lt;/a&gt; for other inspiring ideas. You'll never go back to the old ways of working.&lt;/p&gt;

&lt;p&gt;If you want to tweak the &lt;code&gt;RepoItem&lt;/code&gt; view that we have in our example, every time you make a change you'll need to fetch the repositories again, and you'll quickly hit Github rate limits. Why can't the UI stay on the &lt;code&gt;RepoItem&lt;/code&gt; page while you work on it?&lt;/p&gt;

&lt;p&gt;There are some solutions in React that enable a similar experience, but they're &lt;a href="https://medium.com/javascript-in-plain-english/what-is-react-fast-refresh-f3d1e8401333"&gt;not quite there yet&lt;/a&gt;, and it's definitely not beginner friendly. Instead, every cljs project has hot reload enabled from the start.&lt;/p&gt;

&lt;p&gt;We can hack something together quite easily if we write to local storage every time the state changes, and then read it from the storage on reload. &lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/learn-you-a-cljs-3-33nti?view=editor"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Whatever strategy you use, I strongly suggest you have something, anything, in place that enables HMR without losing state, so that you can experience the joy of live reloading.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 (3) Surgically update components
&lt;/h2&gt;

&lt;p&gt;Some of you might complain that passing the entire state down to the exact component that needs it takes a lot of work. And you will be right. It also forces all the root components to re-render whenever a leaf changes its properties.&lt;br&gt;
That's why all cljs libraries tried to come up with a solution that makes this approach more efficient: om had cursors, reagent had reactive atoms.&lt;/p&gt;

&lt;p&gt;A real breakthrough came with the introduction of re-frame, and with &lt;a href="https://github.com/day8/re-frame/blob/131859d718524f766a60d267725509fca31a7dc5/README.md"&gt;the best README you'll ever see&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You want your components to react only to specific changes of the "memory database". The concept is similar to Materialised Views: they represent a particular view of the underlying database and they update only when the data they're interested in changes. &lt;/p&gt;

&lt;p&gt;I can't find a talk from Mike Thompson, author of re-frame, but he convinced all of us to watch this video, and you should probably watch it too.&lt;/p&gt;

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

&lt;p&gt;Recently, Recoil introduced similar concepts to most React users and its design is heavily inspired by re-frame (a selector is a particular view on an atom and through hooks you subscribe to its updates).&lt;/p&gt;

&lt;p&gt;Recoil is quite smart in its implementation, and nicely enough, you can use the &lt;code&gt;reducer&lt;/code&gt; pattern inside of it: we can keep all the state inside an &lt;code&gt;appAtom&lt;/code&gt; and &lt;code&gt;useRecoilSetState&lt;/code&gt; to update it.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/learn-you-a-cljs-4-5ce2c?view=editor"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here &lt;code&gt;appAtom&lt;/code&gt; in our main db and the other selectors (&lt;code&gt;reposView&lt;/code&gt;, &lt;code&gt;repoItemView&lt;/code&gt; etc)  provide the materialised views. Recoil does the rest, triggering an update when needed. If you click a &lt;code&gt;RepoItem&lt;/code&gt; and set its nested state to &lt;code&gt;isOpen:true&lt;/code&gt;, only that element will rerender &lt;a href="https://github.com/facebookexperimental/Recoil/pull/749"&gt;(if you enable this flag)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Again, I'm over-engineering our example to illustrate how these concepts work, but creating a new selector for each component seems to be quite a common pattern. And I love how business logic (imagine a "is repo actively maintained?" concept) sits in the selector and the UI just consumes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎢 (4) Side effects as data
&lt;/h2&gt;

&lt;p&gt;Last point, I promise.&lt;/p&gt;

&lt;p&gt;We seem to have it all now: centralised state, consistent hot reload, smart updating views. &lt;em&gt;What more&lt;/em&gt;, I hear you say?&lt;/p&gt;

&lt;p&gt;In all the examples above, when it's time to perform a side effect we just go ahead and do it. On the click of a button, we go ahead and hit the network, or persist to local storage, or manipulate the url. Seems easy enough.&lt;/p&gt;

&lt;p&gt;Except that performing the side effects straight away makes it harder to track down what's happening at any given point in your application. Remember the official Architecture Diagram in the re-frame README?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cqpM7Mwp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/day8/re-frame/131859d718524f766a60d267725509fca31a7dc5/images/the-water-cycle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cqpM7Mwp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/day8/re-frame/131859d718524f766a60d267725509fca31a7dc5/images/the-water-cycle.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A side effect can trigger more side effects and/or state changes. It's a first class citizen of our application. And I think we should create an &lt;code&gt;Effect&lt;/code&gt; data structure to represent it, similarly to how we create a reducer &lt;code&gt;Action&lt;/code&gt; to transition the state. &lt;/p&gt;

&lt;p&gt;This is a concept strongly advocated by The Elm Architecture and the Command pattern, and many libraries, including re-frame, have it. There are a few ways to implement this "effects queue" but the simplest is to keep it in the app state, along the "memory db" that holds the data to be visualised by the components. So now we have two top level keys: &lt;code&gt;db&lt;/code&gt; and &lt;code&gt;effects&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/learn-you-a-cljs-5-zbc0p?view=editor"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Recoil, again, makes it pretty clean because your app can just subscribe to the &lt;code&gt;dbView&lt;/code&gt; which holds the ui data as we now it, and a different part of your app can subscribe to the &lt;code&gt;effectsView&lt;/code&gt; and perform the side effects.&lt;/p&gt;

&lt;p&gt;Notice three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We don't need to call useEffects everywhere in our application: there is just one at the root, and all effects are performed there.&lt;/li&gt;
&lt;li&gt;When we execute a branch in the reducer, we no longer just specify how the app state changes, we also declare which side effects will triggered. This is an amazing way to understand the behaviour of your application: "When I click this button I display a loading indicator and start to fetch the data". This is how we humans talk about these concepts, and they're nicely reflected in our code.&lt;/li&gt;
&lt;li&gt;Side effects execution is now explicit. You can inspect it, monitor it, pause it, replay it, persist it, rewind it &lt;a href="https://www.youtube.com/watch?v=fnWypQz6X2U"&gt;(play Daft Punk song here)&lt;/a&gt; because &lt;em&gt;it's just data™&lt;/em&gt;. For example, when a button is clicked you can have a look at the effects queue and decide to remove any pending http side effects if the user is navigating to another screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you model side effects explicitly you can have fantastic insight on your app behaviour: check the &lt;a href="https://jacekschae.github.io/conduit-re-frame-10x-demo/"&gt;re-frame-10x demo&lt;/a&gt; or the &lt;a href="https://www.youtube.com/watch?v=2HK4ENBPcWA"&gt;Elm Time Travel Debugger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I know some of you might think: ugh, is it worth the effort? And the answer is yes, believe me. And if you don't believe me, believe success of the tool you're already using: isn't React just a way to model DOM side effects through explicit data instead of executing them directly?&lt;/p&gt;

&lt;h2&gt;
  
  
  🕵 Conclusion: where is the library
&lt;/h2&gt;

&lt;p&gt;You might be thinking: ok, interesting ideas, but you talked about all of this because you have a library to pitch, don't you? You don't expect me to write this myself, do you, so where's the download link and the Quick Start page?&lt;/p&gt;

&lt;p&gt;Sorry, there's no library. If there was it would be called &lt;code&gt;The Kappa Architecture for React&lt;/code&gt;, or simply &lt;code&gt;reframejs&lt;/code&gt;, but there's no need for it. And this is not even a pitch to say: all these things you can have if you switch to ClojureScript. Because it's not a particular framework or library: it's a set of related concepts. Sure, they feel more at home in a cljs project but they work nicely in plain React too, and I used them to create &lt;a href="https://github.com/frankiesardo/buzzer-multiplayer"&gt;this simple multiplayer buzzer app&lt;/a&gt; if you want to see them in action.&lt;/p&gt;

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