<?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: João</title>
    <description>The latest articles on DEV Community by João (@joaomarcusc).</description>
    <link>https://dev.to/joaomarcusc</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%2F25110%2Fc45c26af-16df-446d-93a1-b7c5ea331cc7.png</url>
      <title>DEV Community: João</title>
      <link>https://dev.to/joaomarcusc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joaomarcusc"/>
    <language>en</language>
    <item>
      <title>Keyboard Layouts and Cognitive Overhead</title>
      <dc:creator>João</dc:creator>
      <pubDate>Tue, 22 Nov 2022 22:18:09 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/keyboard-layouts-and-cognitive-overhead-jd7</link>
      <guid>https://dev.to/joaomarcusc/keyboard-layouts-and-cognitive-overhead-jd7</guid>
      <description>&lt;p&gt;Before I start talking about my experience with mechanical keyboards and what it has to do with Cognitive Overhead, it's important to explain that the latter is. &lt;/p&gt;

&lt;p&gt;When explaining what Cognitive Overhead means, David Lieb uses the definition coined by web designer and engineer in Chicago David Demaree: Cognitive Overhead — “how many logical connections or jumps your brain has to make in order to understand or contextualize the thing you’re looking at.”&lt;br&gt;
Source: &lt;a href="https://techcrunch.com/2013/04/20/cognitive-overhead/?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+Techcrunch+%28TechCrunch%29&amp;amp;curator=MediaReDEF"&gt;Cognitive Overhead, Or Why Your Product Isn’t As Simple As You Think&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first mechanical keyboard I tried was a cheaper Coolermaster one. Apart from not having the numerical keypad, it was a conventional keyboard layout. I realized back then I do not miss the numpad at all because I pretty much never use it anyway. So, it's actually one less thing to worry about, and thus less cognitive overhead to me.&lt;/p&gt;

&lt;p&gt;Afterwards, I decided to use an Ultimate Hacking Keyboard. It was a split keyboard - literally, the left and the right sides can be split, joined by one cable. It was a bit of cognitive overhead, but not that much. I could get used to it in a couple of days. The lack of separate arrows and function keys got more time to get used to, though. Fortunately, it had a wonderful "mouse mode" which let me use the keyboard as a mouse. I ended up learning to use the mouse mode instead of the arrow keys. So, a kind of tradeoff: the cognitive overhead of having to learn the positions of the different keys was compensated by using the mouse mode, which was simpler.&lt;/p&gt;

&lt;p&gt;Unfortunately, I spilled coffee all over my UHK, and couldn't save it. I had to buy another keyboard, and decided to try... Moonlander Mark I. And damn, that was a cognitive overhead nightmare to me. The columnar layout was the first one, but not so much: I surprisingly got used to it in a matter of hours. Having to use thumb keys to get access to arrows and function keys was a bit too much to me, though. I know other people get used do it, but I was actually getting scared of hitting the wrong key and press delete instead of Home/End for example. The thumb keys were very uncomfortable as well, so yet another cognitive overhead issue to me. I decided to sell it and buy a... Dygma Raise. Why didn't I pick a more conventional keyboard? I don't know, I just wanted to try something different.&lt;/p&gt;

&lt;p&gt;Dygma Raise is amazing. Build quality is top-notch, it's a sturdy beast, it's easy to customize and completely programmable. The thumb keys were much better positioned and easier to use. I thought I was going to get used to it, but I slowly realized I actually did not like non-conventional keyboards at all! Needing to press a modifier key to get access to arrows, home/end, F1...F12 keys was slowly draining some mental health out of me. Why? You guessed it... cognitive overhead!&lt;/p&gt;

&lt;p&gt;What I now understand is that I was fighting against decades of muscle memory. Using a more conventional keyboard layout for an hour is enough for me to get all my muscle memory back to normal. I bought a Logitech G912 TKL (TenKeyLess, meaning without the numerical pad because that's one thing I don't miss) this time. I'm not telling you to not use mechanical keyboards at all, but just keep in mind that cognitive overhead is a big thing that causes a lot of stress. It might pay off in the end, but sometimes the price is too high.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Vim/NeoVim as a (very) simple REST client</title>
      <dc:creator>João</dc:creator>
      <pubDate>Thu, 15 Apr 2021 15:32:31 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/vim-as-a-very-simple-rest-client-1aj7</link>
      <guid>https://dev.to/joaomarcusc/vim-as-a-very-simple-rest-client-1aj7</guid>
      <description>&lt;p&gt;Whenever you need to test APIs, you can probably resort to nice GUIs like Postman or Insomnia. They let you easily create separate projects, separate API paths, and so on. I do not like to leave my editor so often, so sometimes I just want to do the API calls inside it. If you use Vim, you can just run cUrl, httpie or some other HTTP client and paste the output on your buffer. &lt;/p&gt;

&lt;p&gt;The following function is very handy because you can use pretty much any shell command you want and the output will be handily updated in your editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; Exec_on_term&lt;span class="p"&gt;(&lt;/span&gt;cmd&lt;span class="p"&gt;,&lt;/span&gt; pos&lt;span class="p"&gt;)&lt;/span&gt;
  exec &lt;span class="s2"&gt;"normal! ma"&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; backup_a&lt;span class="p"&gt;=&lt;/span&gt;@&lt;span class="k"&gt;a&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; backup_b&lt;span class="p"&gt;=&lt;/span&gt;@&lt;span class="k"&gt;b&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; sep &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"------"&lt;/span&gt;
  exec &lt;span class="s2"&gt;"normal! ?"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;sep&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"\&amp;lt;CR&amp;gt;jV/"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;sep&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"\&amp;lt;CR&amp;gt;k\"ay"&lt;/span&gt;
  exec &lt;span class="s2"&gt;"normal! /"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;sep&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"\&amp;lt;CR&amp;gt;jO"&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;a:pos&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
      exec &lt;span class="s2"&gt;"normal! O"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;sep
      exec &lt;span class="s2"&gt;"normal! jddkko"&lt;/span&gt;
  &lt;span class="k"&gt;endif&lt;/span&gt;
  exec &lt;span class="s2"&gt;"normal! V/"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;sep&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"\&amp;lt;CR&amp;gt;kdO"&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; @&lt;span class="k"&gt;b&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;@&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"put b"&lt;/span&gt;
  &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"normal! ?"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;sep&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"\&amp;lt;CR&amp;gt;jdd"&lt;/span&gt;
  exec &lt;span class="s2"&gt;"normal 'a"&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; @&lt;span class="k"&gt;b&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;backup_b
  &lt;span class="k"&gt;let&lt;/span&gt; @&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;backup_a
&lt;span class="k"&gt;endfunction&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;dr&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; Exec_on_term&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"normal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"curr"&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
vnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;F6&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;u&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; Exec_on_term&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"visual"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"curr"&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;dn &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; Exec_on_term&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"normal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, if you have the following buffer contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----------
curl -H "Content-Type: application/json" \
-X POST  \
https://reqbin.com/echo/post/json \
-s -d '{"sample": "value"}'
-----------
output will be shown here
----------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You just need to go anywhere between the first "-------" line and the second "------" line, and type &lt;code&gt;&amp;lt;Leader&amp;gt;dr&lt;/code&gt; (in my Vim config, Leader is the comma character, so &lt;code&gt;,dr&lt;/code&gt; here. It will run the command and show the output between the second and the third "-------" lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;----------------
curl -H "Content-Type: application/json" \
-X POST  \
https://reqbin.com/echo/post/json \
-s -d '{"sample": "value"}'
----------------
{"success":"true"}
----------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you change the command, it will replace the output. If you do not want to replace the contents, you can add a new entry by using &lt;code&gt;&amp;lt;Leader&amp;gt;dn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;----------------
curl -H "Content-Type: application/json" \
-X POST  \
https://reqbin.com/echo/post/json \
-s -d '{"sample": "value"}'
----------------
{"success":"true"}
-----------
output will be shown here
---------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run any CLI command, like Python code by using &lt;code&gt;python -c&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---------------------
python -c '
import os
print("this is a python script")
'
---------------------
this is a python script
---------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>React: Criando  Hooks Customizados</title>
      <dc:creator>João</dc:creator>
      <pubDate>Tue, 11 Aug 2020 17:09:19 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/react-criando-hooks-customizados-1l8l</link>
      <guid>https://dev.to/joaomarcusc/react-criando-hooks-customizados-1l8l</guid>
      <description>&lt;p&gt;Uma das características mais importantes que um código pode ter é o reuso. É bom poder encapsular funcionalidades específicas em uma classe ou função. Esse é, na minha opinião, um probleminha com componentes de classe no React. Você precisa usar métodos do ciclo de vida do componente, como &lt;code&gt;componentDidMount&lt;/code&gt; e &lt;code&gt;componentWillUnmount&lt;/code&gt;. Fica mais difícil encapsular tudo isso. Você precisa alterar seus componentes, mudando a hierarquia da classe, adicionando contexts com providers ou algo do tipo. Não há algo que você possa simplesmente "plugar" no seu componente.&lt;/p&gt;

&lt;p&gt;É aqui que o uso de componentes de função pode vir a calhar, já que os Hooks e Effects do React podem ser muito bem aproveitados. O objetivo deste pequeno artigo é mostrar como você pode utilizar encapsular específicas para sua aplicação lançando mão de Hooks. Por exemplo, o componente abaixo, extraído de um caso de uso real, permite ao usuário a entidade atual (um usuário, um aluno, um professor, uma empresa, etc):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FavoriteEntitiesSection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;false&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;currentEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&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;refreshFavoriteEntities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchCurrent&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;refreshFavoriteEntities&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="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someCleanupAction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFavorite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;setCurrentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isFavorite&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;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePinEntityButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleRemoveEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeFavoriteEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshFavoriteEntities&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="o"&gt;&amp;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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handlePinEntityButtonClick&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;Pin&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;favoriteEntities&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;entity&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;removeEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Remove&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="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="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;E se nós quisermos usar esses favoritos em outro lugar? Poderíamos simplesmente incluir esse componente inteiro, mas pode ser que nós queiramos somente a listagem, pode ser que queiramos somente saber se a entidade atual está nos favoritos, etc. Isso pode ser resolvido incluindo tudo no Redux? Sim, mas nem sempre isso é desejável. Vamos refatorar esse código para que a funcionalidade de "favoritos" fique encapsulada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;useFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadAtMount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;false&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;isRefreshing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsRefreshing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;false&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;currentEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&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;refreshFavoriteEntities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isRefreshing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;setIsRefreshing&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="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchCurrent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&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;setIsRefreshing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadAtMount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;refreshFavoriteEntities&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someCleanupAction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFavorite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;setCurrentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isFavorite&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;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saveCurrentEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;removeEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;FavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshFavoriteEntities&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="nx"&gt;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;refreshFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;saveCurrentEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;removeEntity&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FavoriteEntitiesSection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;favoriteEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;saveCurrentEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;removeEntity&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="nx"&gt;useFavoriteEntities&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;currentEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&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;handlePinEntityButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;saveCurrentEntity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleRemoveEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;removeEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="o"&gt;&amp;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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentEntityIsFavorite&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handlePinEntityButtonClick&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;Pin&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;favoriteEntities&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;entity&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;handleRemoveEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Remove&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="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="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;Perceba como o componente deixa de se preocupar com a lógica em torno dos favoritos, inclusive com a atualização automática: tudo é feito dentro da função. Fica até mais fácil dar uma incrementada nas funcionalidades, como eu fiz no exemplo acima:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chamadas repetidas ao &lt;code&gt;refreshFavoriteEntities&lt;/code&gt; não vão gerar chamadas desnecessárias ao serviço.&lt;/li&gt;
&lt;li&gt;Tentativas de salvar um favorito que já foi salvo não geram duplicações&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Além disso. se em algum outro componente precisar somente da listagem, basta usar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;favoriteEntities&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFavoriteEntities&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Espero que esse exemplo ajude a entender como tirar vantagem dos Hooks no React! Afinal, não pode ser só choro e ranger de dentes, de vez em quando tem que haver alguma vantagem.&lt;/p&gt;

</description>
      <category>react</category>
      <category>hooks</category>
      <category>ptbr</category>
      <category>brazilian</category>
    </item>
    <item>
      <title>What to do when rebase goes wrong?</title>
      <dc:creator>João</dc:creator>
      <pubDate>Fri, 03 Jul 2020 15:02:09 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/what-to-do-when-rebase-goes-wrong-224i</link>
      <guid>https://dev.to/joaomarcusc/what-to-do-when-rebase-goes-wrong-224i</guid>
      <description>&lt;p&gt;Git (and other DVCS such as Mercurial) makes branches &lt;em&gt;much&lt;/em&gt; easier than the previous, non-distributed versions. It is also very powerful, but sometimes things can go really wrong. One common issue is using &lt;code&gt;git rebase&lt;/code&gt; when a branch is outdated and points to an old commit from master. Older branches can lead to a &lt;em&gt;lot&lt;/em&gt; of conflicts, making rebase a nightmare. The purpose of this blog post is to show you some ways you can save time and probably your sanity using rebase. This is a specific to a simple branch rebase that's often needed when the branch is based on a commit that's just too old. &lt;/p&gt;

&lt;p&gt;The simplest solution is to just use &lt;code&gt;git merge&lt;/code&gt;, but there are some reasons why you may not want to do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It pollutes the tree with merge commits. Depending on the number of commits, it can look quite messy. In my case, the repository constantly receives hundreds of commits in a single day. &lt;/li&gt;
&lt;li&gt;If you're using Pull Requests or Phabricator diffs, using &lt;code&gt;git merge&lt;/code&gt; is not recommended.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suppose we have a &lt;code&gt;feature&lt;/code&gt; branch. First, you need to the commit at &lt;code&gt;master&lt;/code&gt; that started your branch. In the following image, it's &lt;code&gt;C2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ReUJr2lh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d8u325axvokjbyxfsb9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ReUJr2lh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d8u325axvokjbyxfsb9n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find it by using the &lt;code&gt;git merge-base&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git merge-base master feature
c2ff9421e78bd5e8f5d9c72702439f989e3f10e0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we have the base commit for the branch, let's generate a patch for your branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git diff --patch c2ff9421e78..feature &amp;gt; feature.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that you have your patch for the whole branch, switch to master, retrieve the latest changes and create a new branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git switch master
$ git pull
$ git checkout -b feature-rebase-temp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What we do now is just apply the patch. What difference does it make? Well, it will expose absolutely all conflicts right away, instead of complaining about at conflicts at each single commit of the &lt;code&gt;feature&lt;/code&gt; branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ patch -p1 --merge &amp;lt; feature.patch
... resolve all conflicts
$ git commit -m "Your message"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This branch is now corresponding to the post-rebase state of your &lt;code&gt;feature&lt;/code&gt; branch. If you are okay with not having the commit history of your feature branch, you can just make the &lt;code&gt;feature-temp&lt;/code&gt; branch your &lt;code&gt;feature&lt;/code&gt; branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git branch -m feature feature-outdated
$ git branch -m feature-temp feature
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You lose the previous history, but in my experience this is the safest route when your branch and master differ way too much, you don't risk losing changes and have all the conflicts at once. &lt;/p&gt;

</description>
      <category>git</category>
      <category>rebase</category>
    </item>
    <item>
      <title>New Life, new Horizons, New Job</title>
      <dc:creator>João</dc:creator>
      <pubDate>Fri, 04 Oct 2019 14:00:11 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/new-life-new-horizons-new-job-3kdl</link>
      <guid>https://dev.to/joaomarcusc/new-life-new-horizons-new-job-3kdl</guid>
      <description>&lt;p&gt;I've been working at &lt;a href="http://www.serpro.gov.br"&gt;SERPRO&lt;/a&gt; for 10 years. Ten years is a lot of time in the IT field. Fortunately, I learned a &lt;strong&gt;lot&lt;/strong&gt; about development, working with people, working with bureaucracy, and many, many other professional lessons. Work wasn't bad, actually. It was frustrating sometimes, but the salary was nice, coworkers were great people and I had some freedom to study and opt for new technologies, at least given the limits of a large public company. Oh, and I had job stability, which is the dream of the vast majority of the Brazilian. The political landscape in Brazil is ridiculously unstable, and so is the economy. &lt;/p&gt;

&lt;p&gt;I felt that something was missing, though. You know that gut feeling that you should be doing something else? So, I decided to assess my skills in the market, see how I would do out of Serpro. I was quite surprised to see I was quite qualified, actually! I never wanted to be the kind of guy that lives in the public sector, afraid of losing my job and not being able to relocate without a major hit on my salary. &lt;/p&gt;

&lt;p&gt;As everyone in the world probably knows, the Brazilian government is not something we are proud of. They are also not exactly fond of owning a public IT company, so they want to privatize it. It's a good thing that I already got a good job proposal before I could quit Serpro.&lt;/p&gt;

&lt;p&gt;So, goodbye Serpro, and welcome, BairesDev! I'm quite happy with my new job, and I hope I can bring my skills to the table. This feels almost like a new life to me. After all, it's been 10 years in the public field, and I fortunately didn't lose my mojo. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Myth about Javascript ecossystem's descent into hell</title>
      <dc:creator>João</dc:creator>
      <pubDate>Wed, 05 Jun 2019 13:52:16 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/the-myth-about-javascript-ecossystem-s-descent-into-hell-4l52</link>
      <guid>https://dev.to/joaomarcusc/the-myth-about-javascript-ecossystem-s-descent-into-hell-4l52</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Warning: grumpy programmer that's been working with Javascript since  Netscape 4 (1999 I guess)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm becoming a different kind of an old fart: the one who doesn't really miss the good ol' times when we didn't have so many any JS libraries and frameworks and everything was so simple (or so they say). I would take new JS technologies over the old, pre-NPM-projects era any day.&lt;/p&gt;

&lt;p&gt;Yeah, I know it's sometimes frustrating to need to download zillions of dependencies so we can build a simple "Hello World" app. I can easily see the point of using Vanilla JS or jQuery even for greenfield projects. Someone who has pretty much only worked with JS libraries and frameworks such as React, Angular, Vue, etc may find jQuery or vanilla JS a breathe of fresh air. It may seem to be a great idea. After all, who needs so many external dependencies when we can just fetch data and render smaller jQuery UI components?&lt;/p&gt;

&lt;p&gt;So, you just start rewriting that old overdone code with small JS files and simple HTML. After a couple of months/years later, you start realizing there's something not quite right about your code. You spot Javascript monsters breaking and turning the state into a spaghetti dragon firing meatballs. Then, one may think "what if we create a library that kind of lets us control page state more easily? Let's give it a name that sounds like it reacts to changes". Ring any bells?&lt;/p&gt;

&lt;p&gt;There is a bright side to opting for vanilla JS, though. One may find, indeed, several cases where using a library is not necessary. Do you really need a "is-number-equals-to-zero" library? What about "return-false-when-object-equals-to"? Don't forget that maybe there is a reason why people choose NPM projects, etc, even guys that do web development since we didn't even have AJAX and jQuery was a pipe dream. &lt;/p&gt;

&lt;p&gt;Vanilla JS or plain jQuery are great for really small scripts, but remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most apps are usually seemingly small and trivial at first&lt;/li&gt;
&lt;li&gt;When you project grows beyond a certain point, vanilla JS may give you headaches&lt;/li&gt;
&lt;li&gt;Know as much about vanilla JS as possible, sometimes you can just use it instead of some library.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Using Svelve for Plone add-ons</title>
      <dc:creator>João</dc:creator>
      <pubDate>Mon, 03 Jun 2019 19:46:30 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/using-svelve-for-plone-add-ons-536h</link>
      <guid>https://dev.to/joaomarcusc/using-svelve-for-plone-add-ons-536h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Zope/Plone bashing follows. If you like Zope/Plone, that's okay, just&lt;br&gt;
skip the first paragraph and I promise you'll read no bashing!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don't like Plone. Okay, actually, I don't like Zope/ZODB. It's overly complex, &lt;em&gt;VERY&lt;/em&gt; inneficient, difficult to maintain, quite fragile. Plone itself is a miracle. The people behind it should be canonized as saints and revered as geniuses. They managed to do something actually usable with the mess that is Zope. Why I'm bashing Zope if I'm going to talk about Plone? Well, I have a job. My job is not to only work with technologies that I like. My job is to work with technologies that I have to. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;End of Zope/Plone bashing, carry on!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;I needed to develop an add-on which included a view that calls an internal server to search for specific results and render them differently depending on the context. There's not much to it, except the UI, which is not too complex, but complex enough for me to not like using vanilla JS, jQuery or simple ZPT templates. I first tried React, because it Plone 6 &lt;a href="https://plone.org/roadmap/2019-plone-roadmap"&gt;will ship&lt;/a&gt; with a &lt;a href="https://github.com/plone/volto"&gt;React-based frontend&lt;/a&gt;. I managed to make it work with Plone 5, for then I had a problem: I still needed to support Plone 4, and then I found my solutions too bug-prone. &lt;/p&gt;

&lt;h1&gt;
  
  
  A solution: Svelte
&lt;/h1&gt;

&lt;p&gt;I thought to myself: "What I need is something that doesn't require any external dependency at all". Then I remembered reading something about &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt;, because, well, it promised to be a "disappearing" library that outputs just plain Javascript that I would just need to include in my add-on. Does it work? Turns out it does! Here is a sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&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;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&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;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello {name}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you build it, the output is a Javascript file that does &lt;em&gt;not&lt;/em&gt; need Svelte itself: it's a self-contained file that can easily be used inside a page with a simple JS entry. The CSS is split into a separate file as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"my-built-app.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"my-built-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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"appContainer"&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&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// target is the element where the component will be rendered&lt;/span&gt;
    &lt;span class="c1"&gt;// props are the properties that the components need&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&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;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;target&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;appContainer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elvis Presley&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Hands-on: Using Svelte inside an add-on
&lt;/h1&gt;

&lt;p&gt;For this hands-on, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The latest Node.js version. I highly recommend using &lt;a href="https://github.com/nvm-sh/nvm"&gt;NVM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A Plone installation that includes a &lt;code&gt;develop.cfg&lt;/code&gt; configuration&lt;/li&gt;
&lt;li&gt;Knowledge on how to &lt;a href="https://docs.plone.org/develop/addons/bobtemplates.plone/README.html"&gt;develop add-ons using Mrbob&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create a sample add-on product
&lt;/h2&gt;

&lt;p&gt;First, create a sample add-on product using mrbob inside the &lt;code&gt;src&lt;/code&gt; directory of the plone instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mrbob &lt;span class="nt"&gt;-O&lt;/span&gt; svelte.sample collective.mrbob:addon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, add it to the &lt;code&gt;develop.cfg&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
[sources]
svelte.sample = fs svelte.sample
...

eggs +=
    ...
    svelte.sample   

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



&lt;h2&gt;
  
  
  Add the initial structure
&lt;/h2&gt;

&lt;p&gt;For now, let's just add a file inside &lt;code&gt;src/svelte/sample/browser/static/sample.js&lt;/code&gt; that will output something to the console so we can tell everything's ok for now. We will replace it with the component later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte.sample Javascript included&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Add a View
&lt;/h2&gt;

&lt;p&gt;The Svelte sample will be run inside a simple view, so, let's first add it to &lt;code&gt;configure.zcml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;  ...
  &lt;span class="nt"&gt;&amp;lt;browser:page&lt;/span&gt;
      &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"svelte-sample"&lt;/span&gt;
      &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;
      &lt;span class="na"&gt;permission=&lt;/span&gt;&lt;span class="s"&gt;"zope2.View"&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;".views.SampleView"&lt;/span&gt;
      &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The view is inside the views module, so, let's create it inside &lt;code&gt;src/svelte/sample/views.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;Products.Five.browser.pagetemplatefile&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ViewPageTemplateFile&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BrowserView&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="n"&gt;ViewPageTemplateFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'templates/sample.pt'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now need the template, so, create the file &lt;code&gt;src/svelte/sample/templates/sample.pt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:metal=&lt;/span&gt;&lt;span class="s"&gt;"http://xml.zope.org/namespaces/metal"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:tal=&lt;/span&gt;&lt;span class="s"&gt;"http://xml.zope.org/namespaces/tal"&lt;/span&gt;
     &lt;span class="na"&gt;metal:use-macro=&lt;/span&gt;&lt;span class="s"&gt;"context/main_template/macros/master"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;metal:block&lt;/span&gt; &lt;span class="na"&gt;fill-slot=&lt;/span&gt;&lt;span class="s"&gt;"javascript_head_slot"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"++plone++svelte.sample/sample.js"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/metal:block&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;metal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Nothing&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt; &lt;span class="nx"&gt;yet&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/metal:block&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/html&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;Now we have a working add-on. If you run the Plone instance, install it and open the &lt;code&gt;@@svelte-sample&lt;/code&gt; view, it will show a page containing "Nothing here yet", and the console will show 'selvte.sample Javascript included'. The add-on itself won't depend on anything else, but we obviously need to create the Svelte components. Thus, we need to create a Svelte project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Svelte project
&lt;/h2&gt;

&lt;p&gt;Creating the project itself is easy. We will be creating the JS project inside our add-on source for this hands-on. Inside the project's root directory, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx degit sveltejs/template component
&lt;span class="nb"&gt;cd &lt;/span&gt;component
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, modify the file &lt;code&gt;component/src/App.svelte&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uppercaseName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&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;h1&amp;gt;&lt;/span&gt;Hello {uppercaseName}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

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



&lt;p&gt;Before we build the project, we need to tell the builder to just export your components we built, by modifying &lt;code&gt;component/src/main.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, let's build the project and copy the resulting bundle.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;span class="nb"&gt;cp &lt;/span&gt;public/bundle.js ../src/svelte/sample/browser/static/sample.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Add the Svelte component to the view
&lt;/h2&gt;

&lt;p&gt;That's it, now the App component is going to be available when we include our sample.js file inside the Plone's view page. Change the &lt;code&gt;src/svelte/component/templates/sample.pt&lt;/code&gt; file to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:metal=&lt;/span&gt;&lt;span class="s"&gt;"http://xml.zope.org/namespaces/metal"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:tal=&lt;/span&gt;&lt;span class="s"&gt;"http://xml.zope.org/namespaces/tal"&lt;/span&gt;
     &lt;span class="na"&gt;metal:use-macro=&lt;/span&gt;&lt;span class="s"&gt;"context/main_template/macros/master"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;metal:block&lt;/span&gt; &lt;span class="na"&gt;fill-slot=&lt;/span&gt;&lt;span class="s"&gt;"javascript_head_slot"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"++plone++svelte.sample/sample.js"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/metal:block&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;metal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;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;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sampleContainer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sample&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;target&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;sampleContainer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Person&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;/metal:block&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, if you open the &lt;code&gt;@@svelte-sample&lt;/code&gt; view, it should show a big &lt;code&gt;Hello PERSON!&lt;/code&gt;. No external includes needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bottom Line
&lt;/h1&gt;

&lt;p&gt;I'm not saying you should just use Svelte for every single add-on. If you can target Plone5+, you could probably use React. If you, however, plan to support Plone 4 and/or don't want to rely too much on specific dependencies, it may be a good idea do pick Svelte. Just remember that what Svelte does is &lt;em&gt;not&lt;/em&gt; to embed other dependencies inside the resulting JS build. So, my advice is to pick Svelte if you can live without other dependencies and pick React for anything else.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why I chose Akita over NgRx</title>
      <dc:creator>João</dc:creator>
      <pubDate>Tue, 09 Apr 2019 16:44:51 +0000</pubDate>
      <link>https://dev.to/joaomarcusc/why-i-chose-akita-over-ngrx-4adb</link>
      <guid>https://dev.to/joaomarcusc/why-i-chose-akita-over-ngrx-4adb</guid>
      <description>&lt;p&gt;I really like the Redux concept. It allows developers to avoid state manipulation to be spread across the application, leading to difficult to detect inconsistencies, specially when dealing with asynchronous events such as calls to HTTP services. It is not, however, an easy concept to grasp. It may look like an overthought solution that creates more troubles than it solves. Anyway, I decided to give NgRx a try a couple of months ago. And it wasn't a pleasant experience. Let me tell you why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Too much boilerplate
&lt;/h2&gt;

&lt;p&gt;Let's start with the boilerplate issue. Whenever I needed to use NgRx for a specific part of my webapp, I had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a set of actions&lt;/li&gt;
&lt;li&gt;Create a reducer function with a big and ugly switch statement&lt;/li&gt;
&lt;li&gt;Add the reducer to the &lt;code&gt;StoreModule.forRoot&lt;/code&gt; or &lt;code&gt;StoreModule.forFeature&lt;/code&gt; call.&lt;/li&gt;
&lt;li&gt;Call the&lt;code&gt;select&lt;/code&gt; function in my component or create selectors to get the current state.&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;dispatch&lt;/code&gt; function to dispatch an action. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What if I needed to fetch data from a service? Well, then I'd have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an action that will be dispatched when data needs to be fetched&lt;/li&gt;
&lt;li&gt;Add an action that will be dispatched when the call finished successfully&lt;/li&gt;
&lt;li&gt;Add an action that will be dispatched when the call fails&lt;/li&gt;
&lt;li&gt;Add an Effects class that will call the data fetch service itself and do the action dispatching&lt;/li&gt;
&lt;li&gt;Add the Effects class to the &lt;code&gt;EffectsModule&lt;/code&gt; call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not a big problem if it's not often needed. Data feching is what I mostly do, though! Effects can become huge and not so easy to maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Too many concepts
&lt;/h2&gt;

&lt;p&gt;I have to admit, a part of our problem is that developers only knew AngularJS (1.5), not Angular (2+). They had to learn about components, modules, DI. I know AngularJS had them before, but Angular (2+) is so different it feels like a new framework. They also had to learn about RxJS, Observables, and other concepts that aren't trivial. And then, suddenly, they also had to learn about Actions, Dispatchers, Reducers, Effects, Selectors! Maybe I should've seen it coming, but even if they already felt comfortable with Angular, it seems that those concepts aren't easy to grasp unless you knew Redux(-ey) libraries before.&lt;/p&gt;




&lt;h2&gt;
  
  
  NgRx feels alien to Angular
&lt;/h2&gt;

&lt;p&gt;Whenever I was using NgRx, I felt like maybe it could make more use of Angular. For example, instead of the big and ugly reducer, decorators should be used by default. Some libraries try to solve that problem, but they felt subpar to me, and they sometimes introduced even more complexity, like needing specific work to avoid problems with AOT compilation. If you're using NgRx, I recommend &lt;a href="https://github.com/amcdnl/ngrx-actions"&gt;ngrx-actions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My coworkers had a very, very difficult time "getting" NgRx, and they spent more time trying to understand NgRx along with Angular than developing the application itself. So, we decided to drop NgRx entirely and letting everyone do as they please, because there was a deadline to meet. &lt;/p&gt;




&lt;h2&gt;
  
  
  Dropping Redux? Not yet!
&lt;/h2&gt;

&lt;p&gt;I didn't quit trying do use Redux-style libraries in my app, but I decided to try the alternatives. Two of them looked more mature and well-tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ngxs.gitbook.io/ngxs/"&gt;NgXs&lt;/a&gt;: More simple than NgRx, but it still had some specific parts that irritates developers, such as the need to declare an Action and corresponding specific dispatch method in a separate place.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://opensource.salesforce.com/akita/"&gt;Akita&lt;/a&gt;: Even simpler than NgXs. Instead of actions and dispatchers, just a plain service, even for async calls. Queries are plain observables. &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The winner: Akita
&lt;/h2&gt;

&lt;p&gt;Now, let's see what it takes to introduce Akita in a specific project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a store as a class extending EntityStore&lt;/li&gt;
&lt;li&gt;Create a service that injects the store and expose actions as service methods. No need for actions, reducers, dispatchers, annotated methods, etc. Just plain methods that updates the state.&lt;/li&gt;
&lt;li&gt;Create a class extending QueryEntity so we create selectors&lt;/li&gt;
&lt;li&gt;Need to call a HTTP service? No problem, just create a service method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It could be even easier, but this seems easy enough I can now talk about it without raising many eyebrows. Maybe I will give NgRx or NgXs another chance, but for now I'll stay with the simpler choice.&lt;/p&gt;

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