<?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: Lucas Fernandez</title>
    <description>The latest articles on DEV Community by Lucas Fernandez (@lucferbux).</description>
    <link>https://dev.to/lucferbux</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%2F413888%2F53a2fe3c-8eda-466d-a958-d8107a74fddb.jpg</url>
      <title>DEV Community: Lucas Fernandez</title>
      <link>https://dev.to/lucferbux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucferbux"/>
    <language>en</language>
    <item>
      <title>Introducción a redux</title>
      <dc:creator>Lucas Fernandez</dc:creator>
      <pubDate>Fri, 20 May 2022 00:54:47 +0000</pubDate>
      <link>https://dev.to/lucferbux/introduccion-a-redux-1mi3</link>
      <guid>https://dev.to/lucferbux/introduccion-a-redux-1mi3</guid>
      <description>&lt;p&gt;Hoy vamos a explicar los conceptos más básicos de Redux y React Redux de la forma más concisa posible, primero explicando los conceptos más importantes y luego viendo su implementación tanto en TypeScript "vanilla" como en React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redux
&lt;/h2&gt;

&lt;p&gt;Redux es una biblioteca muy popular de JavaScript que permite manejar el estado de una aplicación. El estado de aplicación es un objeto global que maneja información heterogénea usada por al aplicación, por poner un ejemplo, el estado para controlar la visibilidad de un &lt;em&gt;spinner&lt;/em&gt; si estamos cargando datos en nuestra aplicación.&lt;/p&gt;

&lt;p&gt;Otro de los grandes objetivos del control de estado es pasar información entre componentes sin caer en el &lt;em&gt;prop drilling&lt;/em&gt; o el tener que pasar un mismo valor entre múltiples componentes padre-hijos para completar la cadena.&lt;/p&gt;

&lt;p&gt;Para todo esto necesitamos bibliotecas de manejo de estados como &lt;em&gt;Redux&lt;/em&gt;. &lt;em&gt;Redux&lt;/em&gt; como biblioteca es muy popular porque basa su uso en unos principios muy sencillos e intuitivos, fundamentados en los siguientes patrones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Source Of Truth&lt;/strong&gt;: O "única fuente de veracidad", que básicamente significa que solo tenemos un lugar (llamado &lt;code&gt;Store&lt;/code&gt;) donde vamos a guardar el estado de toda la aplicación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inmutabilidad&lt;/strong&gt;: En &lt;em&gt;Redux&lt;/em&gt; no vamos a cambiar el estado de un objeto y sus propiedades directamente, si no que vamos a crear un nuevo objeto calculando el nuevo estado de la aplicación y así actualizandolo con el nuevo objeto creado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Componentes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jxCgkfMW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7qs1d2j43o1jmuigcqnh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jxCgkfMW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7qs1d2j43o1jmuigcqnh.png" alt="Componentes Redux" width="880" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con estos principios, vamos a ver los componentes esenciales de &lt;em&gt;Redux&lt;/em&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  Store
&lt;/h3&gt;

&lt;p&gt;El &lt;code&gt;Store&lt;/code&gt; o almacenamiento contiene el estado de la aplicación. Este &lt;code&gt;Store&lt;/code&gt; es un objeto con sus funciones y atributos al que podemos suscribirnos para escuchar eventos cuando el objeto &lt;code&gt;Store&lt;/code&gt; se actualiza. Este objeto es referenciado muchas veces como el "árbol de estado", ya que es posible almacenar cualquier valor y anidar tanta información como se necesite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actions
&lt;/h3&gt;

&lt;p&gt;Son objetos JavaScript que describen qué a pasado en un estado, pero no como este estado debe cambiar. Simplemente mandamos (dispatch) estas acciones a nuestro objeto &lt;code&gt;Store&lt;/code&gt; siempre que queramos actualizar el estado. La gestión del cambio será efectuada por los &lt;code&gt;Reducers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Estas acciones son objetos que tienen al menos un atributo, en este caso por convenio es &lt;code&gt;type&lt;/code&gt;, para indicar la acción, y luego el resto de atributos necesarios para indicar la acción.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reducers
&lt;/h3&gt;

&lt;p&gt;Los &lt;code&gt;Reducers&lt;/code&gt; son &lt;strong&gt;funciones puras&lt;/strong&gt; que definen como debe cambiar el estado de la aplicación. Cuando enviamos (dispatch) una &lt;code&gt;Action&lt;/code&gt; a nuestro &lt;code&gt;Store&lt;/code&gt;, la acción pasa a un &lt;code&gt;Reducer&lt;/code&gt; que la interpretará para modificar el estado.&lt;/p&gt;

&lt;p&gt;Una función &lt;code&gt;reducer&lt;/code&gt; toma dos parámetros, el estado previo y la acción que vamos a enviar y devuelve un nuevo estado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;newState&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Básicamente un reducer computará el nuevo estado de la aplicación basándose en el estado (y su tipo) que vamos a enviar. Lo más normal es que a medida que una &lt;em&gt;codebase&lt;/em&gt; se vuelve más compleja, los &lt;code&gt;reducers&lt;/code&gt; aumentarán en funcionalidad y complejidad, es por ello que la mejor estrategia a seguir es dividirlos en múltiples partes y luego combinarlos con la función &lt;code&gt;combineReducers&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flujo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bmt3GKG---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvq823pa4i07o6f45bsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bmt3GKG---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvq823pa4i07o6f45bsn.png" alt="Flujo Redux" width="880" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El flujo de la aplicación es relativamente sencillo conociendo los componentes, solo tenemos que utilizar en conjunto los elementos antes mencionados:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lo primero tendremos que suscribirnos al &lt;code&gt;Store&lt;/code&gt; y tener un mecanismo para reaccionar.&lt;/li&gt;
&lt;li&gt;Ahora en cualquier cambio de estado que queramos hacer, solo tenemos que llamar al método &lt;code&gt;store.dispatch()&lt;/code&gt; con la &lt;code&gt;Action&lt;/code&gt; que queramos realizar.&lt;/li&gt;
&lt;li&gt;Redux gestiona esta acción mediante el &lt;code&gt;Reducer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Al estar suscritos al &lt;code&gt;Store&lt;/code&gt;, nos devolverá el nuevo estado que podremos añadir a nuestra aplicación.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Como veis, incorporar &lt;em&gt;Redux&lt;/em&gt; en nuestra aplicación es relativamente sencillo una vez tenemos todos los conceptos claros. Ahora vamos a ver unos ejemplos prácticos para TypeScript y React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redux + TypeScript
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pRL8taJo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fcc1jegbtbh8p1fdp9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pRL8taJo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fcc1jegbtbh8p1fdp9w.png" alt="Aplicación en TypeScript" width="880" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos a hacer primero una versión en TypeScript &lt;em&gt;vanilla&lt;/em&gt; para asentar los conceptos de forma correcta. Esta aplicación consta de un formulario sencillo con el que añadir recordatorios. Cada vez que pulsemos el botón &lt;em&gt;"Add"&lt;/em&gt;, mandaremos una acción a &lt;em&gt;Redux&lt;/em&gt; con el recordatorio que queremos crear.&lt;/p&gt;

&lt;p&gt;Primero vamos a definir una interfaz para los &lt;em&gt;reminders&lt;/em&gt;, que constará de un atributo &lt;code&gt;title&lt;/code&gt; para el título y &lt;code&gt;description&lt;/code&gt; para la descripción.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Reminder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Ahora vamos a crear nuestra &lt;code&gt;Action&lt;/code&gt;. De momento solo vamos a crear un acción para añadir nuevos recordatorios a nuestro estado global, es por ello que primero definiremos la &lt;code&gt;interface&lt;/code&gt; de nuestra acción, seguido del atributo &lt;code&gt;type&lt;/code&gt; que controlaremos en nuestro &lt;code&gt;reducer&lt;/code&gt; y atributos adicionales como son &lt;code&gt;title&lt;/code&gt; y &lt;code&gt;description&lt;/code&gt; que servirán para crear el recordatorio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ----------- Action ------------&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ReminderAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;ADD_REMINDER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_REMINDER&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addReminder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReminderAction&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ADD_REMINDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;description&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;Ahora generaremos nuestro &lt;code&gt;reducer&lt;/code&gt;. Como es el primero de todos será nuestro &lt;code&gt;rootReducer&lt;/code&gt;, en el que controlaremos todas las acciones con un &lt;code&gt;switch&lt;/code&gt; (en este caso solo tenemos una inicialmente), en la que con un &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;spread operator&lt;/a&gt; añadiremos un nuevo objeto &lt;code&gt;Reminder&lt;/code&gt; en el array de estados de la aplicación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ----------- Reducer ------------ &lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ReminderState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;reminders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reminder&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;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReminderState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reminders&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;rootReducer&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;ReminderState&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReminderAction&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReminderState&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;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="na"&gt;ADD_REMINDER&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="na"&gt;reminders&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reminders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&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="nl"&gt;default&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;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ya solo nos falta crear nuestra &lt;code&gt;store&lt;/code&gt; y añadir nuestro &lt;code&gt;rootReducer&lt;/code&gt; para tener &lt;em&gt;Redux&lt;/em&gt; configurado en nuestra aplicación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ----------- Store ------------ &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootReducer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para la &lt;em&gt;UI&lt;/em&gt;, lo más destacable es que vamos a tener una función llamada &lt;code&gt;renderReminders&lt;/code&gt; que básicamente recoge el estado de nuestro &lt;code&gt;Store&lt;/code&gt; y modifica el DOM de la aplicación para mostrar todos los recordatorios que tengamos guardados. Para que nuestra aplicación reaccione a los cambios vamos a suscribirnos al &lt;code&gt;Store&lt;/code&gt; mediante el método &lt;code&gt;store.subscribe(() =&amp;gt; {})&lt;/code&gt; al que le pasaremos nuestra función para renderizar los recordatorios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ----------- UI ------------&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&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;addButton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;remindersDashboard&lt;/span&gt; &lt;span class="o"&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;reminder-dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;title&lt;/span&gt; &lt;span class="o"&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;titleInput&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&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;description&lt;/span&gt; &lt;span class="o"&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;descriptionInput&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addReminder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&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;renderReminders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reminderState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;reminders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reminderDom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;reminderState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;element&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;reminderDom&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div class="reminder-card"&amp;gt;
            &amp;lt;p class="reminder-title"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
            &amp;lt;p class="reminder-description"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;remindersDashboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reminderDom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&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;renderReminders&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucferbux/embed/eYVWaKP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Redux + React
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xqwu406K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txhc7idbug2hspqml1rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xqwu406K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txhc7idbug2hspqml1rv.png" alt="React App" width="880" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a reutilizar la mayor parte de la estructura del proyecto anterior, ya que las declaraciones de las &lt;code&gt;Actions&lt;/code&gt;, &lt;code&gt;Reducers&lt;/code&gt; y &lt;code&gt;Store&lt;/code&gt; son las mismas. Nuestro objetivo ahora es conectarnos y acceder a nuestro &lt;code&gt;Store&lt;/code&gt; a través de los componentes funcionales de nuestra aplicación. Para ello vamos a hacer uso de la librería &lt;a href="https://react-redux.js.org"&gt;react-redux&lt;/a&gt; y de varios &lt;code&gt;hooks&lt;/code&gt; que nos facilitarán el trabajo.&lt;/p&gt;

&lt;p&gt;Lo primero que vamos a tener que hacer es rodear nuestro componente de aplicación con el &lt;code&gt;Provider&lt;/code&gt; de &lt;em&gt;Redux&lt;/em&gt;, al que le pasaremos el objeto &lt;code&gt;store&lt;/code&gt; que hemos declarado previamente. Con ello ya podremos acceder al &lt;code&gt;Store&lt;/code&gt; global desde cualquiera de los componentes de nuestra aplicación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&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;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&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;App&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="sr"&gt;/Provider&amp;gt;, document.querySelector&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;".container"&lt;/span&gt;&lt;span class="se"&gt;))&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos a hablar primero de &lt;code&gt;useSelector&lt;/code&gt;. Este hook permite devolver una parte del objeto &lt;code&gt;Store&lt;/code&gt; a nuestro componente. El selector va a hacer una comprobación del estado anterior, y si no es el mismo, el componente accionará un renderizado. Este &lt;code&gt;hook&lt;/code&gt; acepta un segundo parámetro que permite modificar la estrategia de comparación entre estados, en este caso usaremos &lt;code&gt;shallowEqual&lt;/code&gt; para que no renderice el componente si en el cambio de estado los valores permanecen igual.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RemindersComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reminders&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;reminders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shallowEqual&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="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reminders-dashboard&lt;/span&gt;&lt;span class="dl"&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;reminders&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;reminder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reminder-card&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;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reminder-title&lt;/span&gt;&lt;span class="dl"&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;reminder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;/p&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;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reminder-description&lt;/span&gt;&lt;span class="dl"&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;reminder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&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;/p&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&amp;gt; &lt;/span&gt;&lt;span class="err"&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;/&amp;gt;  &lt;/span&gt;&lt;span class="err"&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;Por otro lado tenemos &lt;code&gt;useDispatch()&lt;/code&gt;, que nos permitirá mandar una acción a nuestro &lt;code&gt;Store&lt;/code&gt; para que lo procese el reducer. Es tan fácil como llamar a la función y pasar la &lt;code&gt;Action&lt;/code&gt; que ya teníamos generada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="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="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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&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="dl"&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;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDescription&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="dl"&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;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&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;dispatchReminder&lt;/span&gt; &lt;span class="o"&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addReminder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wrapper&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;HeaderComponent&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Redux + React&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FormComponent&lt;/span&gt; &lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;setDescription&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;submitForm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dispatchReminder&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;           &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RemindersComponent&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="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;Con esto ya tendríamos configurado &lt;em&gt;Redux&lt;/em&gt; en nuestro proyecto &lt;em&gt;React&lt;/em&gt;. Como veis una vez dominamos los conceptos esenciales la implementación es relativamente sencilla. Abajo tenemos un codepen con el ejemplo mencionado antes.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucferbux/embed/XWZRQwZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Saludos 👋&lt;/p&gt;

</description>
      <category>redux</category>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Certificados Digitales</title>
      <dc:creator>Lucas Fernandez</dc:creator>
      <pubDate>Thu, 08 Jul 2021 15:50:57 +0000</pubDate>
      <link>https://dev.to/lucferbux/certificados-digitales-4a6h</link>
      <guid>https://dev.to/lucferbux/certificados-digitales-4a6h</guid>
      <description>&lt;h2&gt;
  
  
  ¿Para qué necesito un certificado?
&lt;/h2&gt;

&lt;p&gt;Desde hace muchos años, la web implementa &lt;strong&gt;SSL (Secure Socket Layer)&lt;/strong&gt; y su sucesor, &lt;strong&gt;TLS (Transport Layer Security)&lt;/strong&gt;, como protocolos para establecer enlaces cifrados entre redes. Es por ello que es esencial el uso de certificados en cualquier servicio web moderno.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es un certificado?
&lt;/h2&gt;

&lt;p&gt;SSL y TLS funcionan mediante certificados de clave pública &lt;strong&gt;x.509&lt;/strong&gt;. Básicamente estos certificados vinculan la identidad de una entidad a un &lt;strong&gt;par de claves criptográficas&lt;/strong&gt;. Cada par consta de una &lt;strong&gt;clave pública&lt;/strong&gt; y una &lt;strong&gt;clave privada&lt;/strong&gt;, la primera se distribuye mediante certificados mientras que la segunda se mantiene segura. Esto permite, mediante el &lt;a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" rel="noopener noreferrer"&gt;criptografía asimétrica&lt;/a&gt;, crear una conexión segura entre un cliente y un servicio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autoridad Certificadora
&lt;/h2&gt;

&lt;p&gt;En este punto es donde entran las &lt;strong&gt;autoridades certificadoras&lt;/strong&gt;. Básicamente son autoridades de confianza que verifican la identidad de los servicios web antes de generar los certificados que hemos mencionado antes. Así, un &lt;strong&gt;navegador web&lt;/strong&gt; tiene ciertas garantías de la legitimidad de una página si el &lt;strong&gt;certificado ha sido emitido por una de estas autoridades&lt;/strong&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%2Fnd07e441bp7pwm6qj4a3.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%2Fnd07e441bp7pwm6qj4a3.png" alt="CA Overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Certificado autofirmado
&lt;/h2&gt;

&lt;p&gt;Vamos ahora a ver cómo generar estos certificados para poder utilizarlos en nuestros servicios. Vamos a empezar con el método más simple, generar estos certificados por nuestra cuenta. Este método es bastante sencillo, pero implica que los navegadores y otras herramientas &lt;strong&gt;generarán alertas al no ser certificados emitidos por una autoridad certificadora&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La herramienta más extendida para generar estos certificados es &lt;a href="https://www.openssl.org/" rel="noopener noreferrer"&gt;OpenSSL&lt;/a&gt;, es por ello que hay que tener instalada esta utilidad como requisito previo. Ahora simplemente hay que seguir los siguientes pasos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generar una clave privada RSA con &lt;a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard" rel="noopener noreferrer"&gt;AES256&lt;/a&gt; con contraseña
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl genrsa &lt;span class="nt"&gt;-aes256&lt;/span&gt; &lt;span class="nt"&gt;-passout&lt;/span&gt; pass:[TU CONTRASEÑA] &lt;span class="nt"&gt;-out&lt;/span&gt; service.pass.key 4096
openssl rsa &lt;span class="nt"&gt;-passin&lt;/span&gt; pass:[TU CONTRASEÑA] &lt;span class="nt"&gt;-in&lt;/span&gt; services.pass.key &lt;span class="nt"&gt;-out&lt;/span&gt; service.key
&lt;span class="nb"&gt;rm &lt;/span&gt;service.pass.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Generar el certificado con la clave privada
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; service.key &lt;span class="nt"&gt;-out&lt;/span&gt; cert.crt &lt;span class="nt"&gt;-days&lt;/span&gt; 365
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Siguiendo estos pasos generaremos un certificado llamado &lt;code&gt;cert.crt&lt;/code&gt; listo para su uso.&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%2Fmnzrldieyoh7kqdaw1g4.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%2Fmnzrldieyoh7kqdaw1g4.png" alt="openssl"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CSR
&lt;/h2&gt;

&lt;p&gt;Si os habéis fijado, antes de crear el fichero, nos han pedido cierta información para generar una &lt;strong&gt;petición de certificado&lt;/strong&gt;. Esto es lo que se conoce como &lt;strong&gt;CSR o Certificate Signing Request&lt;/strong&gt;. Un CSR consiste básicamente en la clave pública de un par de claves e información adicional, como el país del certificado, mail de la empresa firmante, etc. Estos dos componentes se insertan en la creación del certificado. A continuación voy a mostrar como generar un CSR y como generar un certificado con un CSR ya creado, como veréis es muy similar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generar un CSR con una clave privada
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; service.key &lt;span class="nt"&gt;-out&lt;/span&gt; service.csr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Generar certificado mediante un CSR
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 356 &lt;span class="nt"&gt;-in&lt;/span&gt; service.csr &lt;span class="nt"&gt;-signkey&lt;/span&gt; service.key &lt;span class="nt"&gt;-out&lt;/span&gt; service.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Certificado firmado con letsencrypt
&lt;/h2&gt;

&lt;p&gt;Hasta ahora hemos hablado de &lt;strong&gt;certificados autofirmados&lt;/strong&gt;, que están bien para probar servicios en etapa de desarrollo. Pero en el momento que creamos un despliegue en producción es esencial tener certificados emitidos por una autoridad certificadora.&lt;/p&gt;

&lt;p&gt;Entre las muchas entidades certificadoras, personalmente suelo usar &lt;strong&gt;letsencrypt&lt;/strong&gt; y su herramienta &lt;strong&gt;certbot&lt;/strong&gt; de forma automatizada en mis despliegues. Ya que es posible, teniendo un dominio asegurado, generar en pocos pasos certificados que podrán auto-renovarse automáticamente.&lt;/p&gt;

&lt;p&gt;Para ello lo mejor es consultar la página de &lt;a href="https://certbot.eff.org/" rel="noopener noreferrer"&gt;certbot&lt;/a&gt; y seguir los pasos determinados para el despliegue que vayamos a realizar.&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%2F9w9m6amkvingegk7032p.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%2F9w9m6amkvingegk7032p.png" alt="certbot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como habéis podido comprobar, los certificados son algo esencial en cualquier servicio web moderno. Gracias al comportamiento de los navegadores modernos, cualquier servicio con certificados mal configurados, expirados o simplemente sin ellos, son inmediatamente bloqueados, dificultando así su acceso y añadiendo una capa de seguridad. Es por ello muy importante asegurar el &lt;strong&gt;correcto funcionamiento de los certificados en producción&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Espero que este pequeño artículo os haya aclarado algunos conceptos y os ayude en el desarrollo de vuestras plataformas.&lt;/p&gt;

&lt;p&gt;Saludos 👋&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cybersecurity</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
