{"componentChunkName":"component---src-templates-content-template-js","path":"/es/part7/miscelanea","result":{"data":{"markdownRemark":{"html":"<div class=\"content\">\n<h3>Componentes de clase</h3>\n<p>Durante el curso solo hemos utilizado componentes de React que se han definido como funciones de Javascript. Esto no fue posible sin la funcionalidad de <a href=\"https://reactjs.org/docs/hooks-intro.html\">hook</a> que llegó con la versión 16.8 de React. Antes, al definir un componente que usa estado, había que hacerlo usando la sintaxis de <a href=\"https://reactjs.org/docs/state-and-lifecycle.html#converting-a-function-to-a-class\">Class</a> de Javascript.</p>\n<p>Es beneficioso al menos estar familiarizado con los componentes de clase hasta cierto punto, ya que el mundo contiene una gran cantidad de código React antiguo, que probablemente nunca se reescribirá por completo con la sintaxis actualizada.</p>\n<p>Conozcamos las principales características de los componentes de clase produciendo otra aplicación de anécdotas, muy familiar para nosotros. Almacenamos las anécdotas en el archivo <i>db.json</i> usando <i>json-server</i>. El contenido del archivo se toma de <a href=\"https://github.com/fullstack-hy/misc/blob/master/anecdotes.json\">aquí</a>.</p>\n<p>La versión inicial del componente de clase se ve así</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">App</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>h1<span class=\"token operator\">></span>anecdote <span class=\"token keyword\">of</span> the day<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h1<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> App</code></pre></div>\n<p>El componente ahora tiene un <a href=\"https://react.dev/reference/react/Component#constructor\">constructor</a>, en el que no sucede nada en este momento, y contiene el método <a href=\"https://react.dev/reference/react/Component#render\">render</a>. Como se puede suponer, render define cómo y qué se renderiza en la pantalla.</p>\n<p>Definamos un estado para la lista de anécdotas y la anécdota actualmente visible. A diferencia de cuando se usa el hook <a href=\"https://react.dev/reference/react/useState\">useState</a>, los componentes de clase solo contienen un estado. Por tanto, si el estado se compone de varias \"partes\", deben almacenarse como propiedades del estado. El estado se inicializa en el constructor:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">App</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">anecdotes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">current</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>anecdotes<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>no anecdotes<span class=\"token operator\">...</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span></span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>h1<span class=\"token operator\">></span>anecdote <span class=\"token keyword\">of</span> the day<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h1<span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">        <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">          <span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>anecdotes<span class=\"token punctuation\">[</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token operator\">&lt;</span>button<span class=\"token operator\">></span>next<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span></span>      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>El estado del componente está en la variable de instancia <em>this.state</em>. El estado es un objeto que tiene dos propiedades. <i>this.state.anecdotes</i> es la lista de anécdotas y <i>this.state.current</i> es el índice de la anécdota que se muestra actualmente.</p>\n<p>En componentes funcionales, el lugar adecuado para obtener datos de un servidor es dentro de un <a href=\"https://react.dev/reference/react/useEffect\">effect hook</a>, que se ejecuta cuando un componente se renderiza o con menos frecuencia si es necesario, por ejemplo, solo en combinación con el primer renderizado.</p>\n<p>Los <a href=\"https://react.dev/reference/react/Component#adding-lifecycle-methods-to-a-class-component\">métodos de ciclo de vida</a> de los componentes de clase ofrecen la funcionalidad correspondiente. El lugar correcto para desencadenar la obtención de datos de un servidor es dentro del método de ciclo de vida <a href=\"https://react.dev/reference/react/Component#componentdidmount\">componentDidMount</a>, que se ejecuta una vez justo después de que un componente se renderiza por primera vez:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">App</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">anecdotes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">current</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function-variable function\">componentDidMount</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    axios<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:3001/anecdotes'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">anecdotes</span><span class=\"token operator\">:</span> response<span class=\"token punctuation\">.</span>data <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>La función callback de la solicitud HTTP actualiza el estado del componente mediante el método <a href=\"https://react.dev/reference/react/Component#setstate\">setState</a>. El método solo toca las keys que se han definido en el objeto pasado al método como argumento. El valor de la key <i>current</i> permanece sin cambios.</p>\n<p>Llamar al método setState siempre desencadena la re-renderización del componente de clase, es decir que realiza nuevamente un llamado al método <em>render</em>.</p>\n<p>Terminaremos el componente con la posibilidad de cambiar la anécdota mostrada. El siguiente es el código para todo el componente con la adición resaltada:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">App</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">anecdotes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">current</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function-variable function\">componentDidMount</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    axios<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:3001/anecdotes'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">anecdotes</span><span class=\"token operator\">:</span> response<span class=\"token punctuation\">.</span>data <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function-variable function\">handleClick</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> current <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">      Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>anecdotes<span class=\"token punctuation\">.</span>length</span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> current <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>anecdotes<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>no anecdotes<span class=\"token operator\">...</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>h1<span class=\"token operator\">></span>anecdote <span class=\"token keyword\">of</span> the day<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h1<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>anecdotes<span class=\"token punctuation\">[</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">        <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleClick<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>next<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span></span>      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>A modo de comparación, aquí está la misma aplicación como un componente funcional:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>anecdotes<span class=\"token punctuation\">,</span> setAnecdotes<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>current<span class=\"token punctuation\">,</span> setCurrent<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span><span class=\"token punctuation\">{</span>\n    axios<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:3001/anecdotes'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">setAnecdotes</span><span class=\"token punctuation\">(</span>response<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">handleClick</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setCurrent</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">round</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>anecdotes<span class=\"token punctuation\">.</span>length <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>anecdotes<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>no anecdotes<span class=\"token operator\">...</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>h1<span class=\"token operator\">></span>anecdote <span class=\"token keyword\">of</span> the day<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h1<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span><span class=\"token punctuation\">{</span>anecdotes<span class=\"token punctuation\">[</span>current<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>handleClick<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>next<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>En el caso de nuestro ejemplo, las diferencias fueron menores. La mayor diferencia entre los componentes funcionales y los componentes de clase es principalmente que el estado de un componente de clase es un solo objeto y que el estado se actualiza utilizando el método <em>setState</em>, mientras que en los componentes funcionales el estado puede constar de múltiples variables diferentes, con todas ellos tienen su propia función de actualización.</p>\n<p>En 2026, los componentes de clase son en gran medida un artefacto histórico. Todo el desarrollo moderno con React utiliza componentes funcionales con hooks y no hay ninguna razón racional para recurrir a un componente de clase al escribir código nuevo. La propia documentación de React trata los componentes de clase como una API heredada.</p>\n<h3>Límite de errores</h3>\n<p>Aunque los componentes de clase están prácticamente obsoletos, todavía hay una situación en la que no pueden evitarse: los <a href=\"https://es.react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary\">límites de errores</a>. Un límite de errores es un componente que captura errores de JavaScript en cualquier lugar de su árbol de componentes hijo y muestra una interfaz alternativa en vez de bloquear toda la aplicación. En 2026, React aún no ha introducido una alternativa basada en hooks, por lo que los límites de errores siguen teniendo que implementarse como componentes de clase.</p>\n<p>Un límite de errores tiene este aspecto:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">ErrorBoundary</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">hasError</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">error</span><span class=\"token operator\">:</span> <span class=\"token keyword\">null</span> <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">static</span> <span class=\"token function\">getDerivedStateFromError</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">hasError</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> error <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentDidCatch</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error<span class=\"token punctuation\">,</span> info</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'ErrorBoundary caught an error'</span><span class=\"token punctuation\">,</span> error<span class=\"token punctuation\">,</span> info<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>hasError<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n          <span class=\"token operator\">&lt;</span>h2<span class=\"token operator\">></span>Something went wrong<span class=\"token punctuation\">.</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h2<span class=\"token operator\">></span>\n          <span class=\"token operator\">&lt;</span>p<span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>error<span class=\"token punctuation\">.</span>message<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>p<span class=\"token operator\">></span>\n          <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">hasError</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">error</span><span class=\"token operator\">:</span> <span class=\"token keyword\">null</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n            <span class=\"token keyword\">try</span> again\n          <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n      <span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>children\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> ErrorBoundary</code></pre></div>\n<p>Los dos métodos clave del ciclo de vida son <i>getDerivedStateFromError</i>, que actualiza el estado para que el siguiente renderizado muestre la interfaz alternativa, y <i>componentDidCatch</i>, que es un buen lugar para registrar el error en un servicio de notificación de errores.</p>\n<p>Puedes envolver cualquier parte del árbol de componentes con un límite de errores para contener los fallos dentro de ese subárbol:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>ErrorBoundary<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Notes <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>ErrorBoundary<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>ErrorBoundary<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Persons <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>ErrorBoundary<span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Si <i>Notes</i> lanza un error, solo esa sección muestra la interfaz alternativa. <i>Persons</i> continúa funcionando con normalidad.</p>\n<p>Como este es el único caso de uso que queda para los componentes de clase, muchos proyectos utilizan la librería <a href=\"https://github.com/bvaughn/react-error-boundary\">react-error-boundary</a>, que oculta el mecanismo basado en clases tras una cómoda API de componentes funcionales para que nunca tengas que escribir tú mismo un componente de clase.</p>\n<h3>Frontend y backend en el mismo repositorio</h3>\n<p>Durante el curso, hemos creado el frontend y el backend en repositorios separados. Este es un enfoque muy típico. Sin embargo, hicimos el despliegue <a href=\"/es/part3/despliegue_de_la_aplicacion_a_internet#sirviendo-archivos-estaticos-desde-el-backend\">copiando</a> el código de frontend incluido en el repositorio de backend. Un enfoque posiblemente mejor habría sido desplegar el código del frontend por separado.</p>\n<p>A veces, toda la aplicación se coloca en un único repositorio. Una forma habitual y limpia de hacerlo con un stack moderno consiste en mantener el frontend de Vite en un directorio <i>client</i> y el backend de Express en un directorio <i>server</i>, cada uno con su propio <i>package.json</i>. La raíz del repositorio recibe un tercer <i>package.json</i> que actúa como envoltorio práctico con scripts para ejecutar ambos conjuntamente.</p>\n<p>Una estructura mínima de un <a href=\"https://github.com/fullstack-hy2020/monorepo\">repositorio</a> de este tipo tiene el siguiente aspecto:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">app/\n  package.json        (root, scripts only)\n  client/\n    package.json      (Vite + React)\n    vite.config.js\n    src/\n      App.jsx\n  server/\n    package.json      (Express)\n    index.js</code></pre></div>\n<p>El servidor Express de <i>server/index.js</i> proporciona la API y, en producción, también sirve el frontend compilado desde el directorio <i>client/dist</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> express <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'express'</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">const</span> path <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'path'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">const</span> app <span class=\"token operator\">=</span> <span class=\"token function\">express</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>express<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/ping'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token string\">'pong'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">time</span><span class=\"token operator\">:</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toISOString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">// serve the built Vite frontend in production</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">NODE_ENV</span> <span class=\"token operator\">===</span> <span class=\"token string\">'production'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>express<span class=\"token punctuation\">.</span><span class=\"token function\">static</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>__dirname<span class=\"token punctuation\">,</span> <span class=\"token string\">'../client/dist'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  app<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/*splat'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">sendFile</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>__dirname<span class=\"token punctuation\">,</span> <span class=\"token string\">'../client/dist/index.html'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PORT</span> <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3001</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">listen</span><span class=\"token punctuation\">(</span><span class=\"token constant\">PORT</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">server running on port </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">PORT</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Durante el desarrollo, el servidor de desarrollo de Vite se ejecuta en su propio puerto y necesita reenviar las peticiones de la API a Express. Esto se configura en <i>client/vite.config.js</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> defineConfig <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vite'</span>\n<span class=\"token keyword\">import</span> react <span class=\"token keyword\">from</span> <span class=\"token string\">'@vitejs/plugin-react'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">server</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">proxy</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">'/api'</span><span class=\"token operator\">:</span> <span class=\"token string\">'http://localhost:3001'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Con el proxy configurado, una llamada <i>fetch</i> a <i>/api/ping</i> desde el frontend se reenvía automáticamente al servidor Express durante el desarrollo, por lo que nunca es necesario fijar en el código la URL del backend.</p>\n<p>El <i>package.json</i> de la raíz conecta todo mediante un par de scripts:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"dev\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"concurrently \\\"npm run dev --prefix server\\\" \\\"npm run dev --prefix client\\\"\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run build --prefix client\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"start\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"NODE_ENV=production npm start --prefix server\"</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"devDependencies\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"concurrently\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^8.0.0\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Aquí hay un par de aspectos interesantes.</p>\n<p>El script <i>dev</i> utiliza <a href=\"https://github.com/open-cli-tools/concurrently\">concurrently</a>, una pequeña utilidad que ejecuta varios comandos al mismo tiempo y combina su salida en un único flujo del terminal. Sin ella habría que abrir dos terminales independientes, uno para el backend y otro para el frontend.</p>\n<p>La opción <i>--prefix</i> indica a npm qué subdirectorio debe tratar como directorio de trabajo del comando, por lo que <i>npm run dev --prefix server</i> equivale a <i>cd server &#x26;&#x26; npm run dev</i>.</p>\n<p>Por tanto, ejecutar <i>npm run dev</i> desde la raíz inicia en paralelo el servidor de desarrollo de Vite y Express con un solo comando. En este modo, Vite sirve el frontend con sustitución de módulos en caliente: al editar un componente de React, el navegador se actualiza de inmediato sin recargar toda la página. El servidor Express se ejecuta por separado y el proxy de Vite le reenvía las peticiones a <i>/api</i>.</p>\n<p>Ejecutar <i>npm run build</i> compila el frontend en el directorio <i>client/dist</i>. Después, <i>npm start</i> establece <i>NODE_ENV=production</i> e inicia Express, que recoge los archivos estáticos de <i>client/dist</i> y sirve tanto la API como el frontend desde un único puerto. Esta es la configuración que se utilizaría al desplegar en un servidor.</p>\n<p>Como cada parte del proyecto tiene su propio <i>package.json</i>, debes indicar de forma explícita a cuál te diriges al instalar nuevos paquetes. La misma opción <i>--prefix</i> también funciona con <i>npm install</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> axios <span class=\"token parameter variable\">--prefix</span> client     <span class=\"token comment\"># add to the frontend</span>\n<span class=\"token function\">npm</span> <span class=\"token function\">install</span> mongoose <span class=\"token parameter variable\">--prefix</span> server  <span class=\"token comment\"># add to the backend</span></code></pre></div>\n<p>Como alternativa, puedes entrar con <i>cd</i> en el directorio correspondiente y ejecutar allí <i>npm install</i> de la forma habitual.</p>\n<h3>Organización del código en una aplicación React</h3>\n<p>En la mayoría de las aplicaciones del curso hemos seguido la convención de colocar los componentes en un directorio <i>components</i>, los hooks en <i>hooks</i> y el código de comunicación con el servidor en <i>services</i>. Para la aplicación BlogList, esto podría tener el siguiente aspecto:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">src/\n  App.jsx\n  components/\n    Blog.jsx\n    BlogList.jsx\n    LoginForm.jsx\n    Notification.jsx\n  hooks/\n    useField.js\n  services/\n    blogs.js\n    users.js\n  stores/\n    blogStore.js\n    notificationStore.js</code></pre></div>\n<p>Esta agrupación plana por tipo funciona bien para aplicaciones pequeñas.</p>\n<p>Cuando la aplicación utiliza enrutamiento, es habitual añadir un directorio <i>pages</i> —a veces llamado <i>views</i>— para los componentes de nivel superior correspondientes a las rutas, manteniendo los componentes de interfaz reutilizables en <i>components</i>. Esta convención se utiliza en frameworks como <a href=\"https://nextjs.org/docs/pages/building-your-application/routing\">Next.js</a> y se describe en las <a href=\"https://legacy.reactjs.org/docs/faq-structure.html\">preguntas frecuentes de React sobre la estructura de archivos</a>:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">src/\n  App.jsx\n  pages/\n    HomePage.jsx\n    BlogPage.jsx\n    UserPage.jsx\n  components/\n    Blog.jsx\n    BlogList.jsx\n    LoginForm.jsx\n    Notification.jsx\n  hooks/\n    useField.js\n  services/\n    blogs.js\n    users.js\n  stores/\n    blogStore.js\n    notificationStore.js</code></pre></div>\n<p>Sin embargo, cuando el código sigue creciendo, un cambio en una única funcionalidad puede seguir afectando a archivos dispersos por todos los directorios, y tanto <i>components</i> como <i>pages</i> pueden resultar difíciles de recorrer.</p>\n<p>Una respuesta habitual consiste en agrupar los archivos por <i>funcionalidad</i>. La metodología <a href=\"https://feature-sliced.design/\">Feature-Sliced Design</a> formaliza este enfoque, y el proyecto <a href=\"https://github.com/alan2207/bulletproof-react\">bulletproof-react</a> es un ejemplo ampliamente citado de su aplicación práctica:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">src/\n  App.jsx\n  features/\n    blogs/\n      Blog.jsx\n      BlogList.jsx\n      blogService.js\n      blogStore.js\n    users/\n      UserList.jsx\n      userService.js\n    notifications/\n      Notification.jsx\n      notificationStore.js\n  hooks/\n    useField.js</code></pre></div>\n<p>Todo lo relacionado con los blogs se encuentra en un mismo lugar, por lo que añadir o modificar una funcionalidad implica trabajar en un solo sitio en vez de en varios. No existe una única forma correcta de organizar un proyecto grande; la elección adecuada depende del tamaño y la naturaleza de la aplicación.</p>\n<h3>Cambios en el servidor</h3>\n<p>Las aplicaciones que creamos durante este curso obtienen datos del servidor cuando se carga la página y después de las acciones del usuario, pero no tienen forma de enterarse de los cambios realizados por otros usuarios. Si otro usuario añade una nueva entrada de blog, nuestro frontend sencillamente no lo sabe hasta que se actualiza la página. ¿Cómo podemos mantener la interfaz sincronizada con un servidor que cambia de forma independiente?</p>\n<p>El enfoque más sencillo es el <a href=\"https://es.wikipedia.org/wiki/Polling_(inform%C3%A1tica)\">polling</a>: el frontend solicita repetidamente al servidor datos actualizados a intervalos fijos, por ejemplo mediante <a href=\"https://developer.mozilla.org/es/docs/Web/API/setInterval\">setInterval</a>. El polling es fácil de implementar, pero derrochador, porque la mayoría de las peticiones no devuelven nada nuevo.</p>\n<p>Una alternativa más limpia son los <a href=\"https://developer.mozilla.org/es/docs/Web/API/WebSockets_API\">WebSockets</a>, que abren una conexión bidireccional persistente entre el navegador y el servidor. Así, el servidor puede enviar actualizaciones a los clientes conectados en cuanto cambia algo, sin que el cliente tenga que preguntar. Todos los navegadores modernos son compatibles con WebSockets.</p>\n<p>Trabajar directamente con la API de WebSocket puede resultar engorroso. La librería <a href=\"https://socket.io/\">Socket.io</a> la envuelve con una API de más alto nivel y añade reconexión automática y otras facilidades.</p>\n<p>En la <a href=\"/es/part8\">parte 8</a> veremos GraphQL, que incluye un mecanismo de suscripciones que permite al servidor notificar a los clientes los cambios en los datos de forma estructurada.</p>\n<h3>Seguridad en aplicaciones React/node</h3>\n<p>Hasta ahora, durante el curso, no hemos abordado en absoluto la seguridad de la información. Tampoco tenemos mucho tiempo ahora, pero afortunadamente la Universidad de Helsinki cuenta con un curso MOOC <a href=\"https://cybersecuritybase.mooc.fi/module-2.1\">Securing Software</a> que cubre este tema tan importante.</p>\n<p>Sin embargo, echaremos un vistazo a algunas cosas específicas de este curso.</p>\n<p>El Open Web Application Security Project (proyecto abierto de seguridad de aplicaciones web), también conocido como <a href=\"https://www.owasp.org\">OWASP</a>, publica una lista anual de los riesgos de seguridad más comunes en las aplicaciones web. La lista más reciente se puede encontrar <a href=\"https://owasp.org/Top10/\">aquí</a>. Los mismos riesgos se pueden encontrar de un año a otro.</p>\n<p>En la parte superior de la lista encontramos la <i>inyección</i>, lo que significa que, por ejemplo, el texto enviado mediante un formulario en una aplicación se interpreta de forma completamente diferente de lo que pretendía el desarrollador del software. El tipo de inyección más famoso es probablemente la <a href=\"https://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work\">inyección SQL</a>.</p>\n<p>Por ejemplo, si la siguiente consulta SQL se ejecuta en una aplicación vulnerable:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">let</span> query <span class=\"token operator\">=</span> <span class=\"token string\">\"SELECT * FROM Users WHERE name = '\"</span> <span class=\"token operator\">+</span> userName <span class=\"token operator\">+</span> <span class=\"token string\">\"';\"</span></code></pre></div>\n<p>Ahora supongamos que un usuario malintencionado <i>Arto Hellas</i> definiría su nombre como</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Arto Hell-as'; DROP TABLE Users; --</code></pre></div>\n<p>para que el nombre contenga una comilla simple <code>'</code>, que es el carácter inicial y final de un string SQL. Como resultado de esto, se ejecutarían dos operaciones SQL, la segunda de las cuales destruiría la tabla <i>Users</i> de la base de datos.</p>\n<div class=\"gatsby-highlight\" data-language=\"sql\"><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> Users <span class=\"token keyword\">WHERE</span> name <span class=\"token operator\">=</span> <span class=\"token string\">'Arto Hell-as'</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">DROP</span> <span class=\"token keyword\">TABLE</span> Users<span class=\"token punctuation\">;</span> <span class=\"token comment\">--'</span></code></pre></div>\n<p>Las inyecciones de SQL se previenen utilizando <a href=\"https://security.stackexchange.com/questions/230211/why-are-stored-procedures-and-prepared-statements-the-preferred-modern-methods-f\">queries parametrizadas</a>. Con ellas, el input del usuario no se mezcla con la SQL query, en cambio, la base de datos inserta los valores del input en los placeholders de la query (normalmente <code>?</code>):</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"SELECT * FROM Users WHERE name = ?\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>userName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Los ataques de inyección también son posibles en bases de datos NoSQL. Sin embargo, mongoose los previene <a href=\"https://zanon.io/posts/nosql-injection-in-mongodb\">desinfectando</a> las consultas. Puedes encontrar más información sobre el tema, por ejemplo, <a href=\"https://web.archive.org/web/20220901024441/https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb.html\">aquí</a>.</p>\n<p><i>Cross-site scripting (XSS)</i> es un ataque en el que es posible inyectar código JavaScript malicioso en una aplicación web legítima. Luego, el código malicioso se ejecutaría en el navegador de la víctima. Si intentamos inyectar lo siguiente en, por ejemplo, la aplicación de notas:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span><span class=\"token punctuation\">></span></span><span class=\"token script\"><span class=\"token language-javascript\">\n  <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Evil XSS attack'</span><span class=\"token punctuation\">)</span>\n</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>el código no se ejecuta, sino que solo se renderiza como 'texto' en la página:</p>\n<picture><img src=\"/static/7fee25a58d613e21d229e3b3db6c61d0/5a190/32e.png\" alt=\"navegador mostrando notas con intento de XSS\" srcset=\"/static/7fee25a58d613e21d229e3b3db6c61d0/772e8/32e.png 200w,\n/static/7fee25a58d613e21d229e3b3db6c61d0/e17e5/32e.png 400w,\n/static/7fee25a58d613e21d229e3b3db6c61d0/5a190/32e.png 800w,\n/static/7fee25a58d613e21d229e3b3db6c61d0/c1b63/32e.png 1200w,\n/static/7fee25a58d613e21d229e3b3db6c61d0/0d98f/32e.png 1276w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>ya que React <a href=\"https://es.legacy.reactjs.org/docs/introducing-jsx.html#jsx-prevents-injection-attacks\">se encarga de desinfectar los datos en variables</a>. Algunas versiones de React <a href=\"https://medium.com/dailyjs/exploiting-script-injection-flaws-in-reactjs-883fb1fe36c1\">han sido vulnerables</a> a los ataques XSS. Los agujeros de seguridad, por supuesto, han sido reparados, pero no hay garantía de que no vuelvan a suceder.</p>\n<p>Es necesario permanecer alerta cuando se utilizan librerías; si hay actualizaciones de seguridad para esas librerías, se recomienda actualizarlas en nuestras aplicaciones. Las actualizaciones de seguridad para Express se encuentran en la <a href=\"https://expressjs.com/en/advanced/security-updates.html\">documentación de la librería</a> y las de Node se encuentran en <a href=\"https://nodejs.org/en/blog/vulnerability/\">este blog</a>.</p>\n<p>Puedes verificar qué tan actualizadas están tus dependencias usando el comando</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> outdated <span class=\"token parameter variable\">--depth</span> <span class=\"token number\">0</span></code></pre></div>\n<p>El proyecto del año pasado que es utilizado en la <a href=\"/es/part9\">parte 9</a> ya tiene bastantes dependencias desactualizadas:</p>\n<picture><img src=\"/static/b199b453cdb888941aed98daf5c32b0a/5a190/33x.png\" alt=\"salida de npm mostrando dependencias desactualizadas de patientor\" srcset=\"/static/b199b453cdb888941aed98daf5c32b0a/772e8/33x.png 200w,\n/static/b199b453cdb888941aed98daf5c32b0a/e17e5/33x.png 400w,\n/static/b199b453cdb888941aed98daf5c32b0a/5a190/33x.png 800w,\n/static/b199b453cdb888941aed98daf5c32b0a/c1b63/33x.png 1200w,\n/static/b199b453cdb888941aed98daf5c32b0a/29007/33x.png 1600w,\n/static/b199b453cdb888941aed98daf5c32b0a/3a1b1/33x.png 1686w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Las dependencias se pueden actualizar modificando el archivo <i>package.json</i>. La mejor forma de hacerlo es utilizar una herramienta llamada <i>npm-check-updates</i>. Puede instalarse globalmente ejecutando el comando:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> <span class=\"token parameter variable\">-g</span> npm-check-updates</code></pre></div>\n<p>Usando esta herramienta, la actualización de las dependencias se verifica de la siguiente manera:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ npm-check-updates\nChecking <span class=\"token punctuation\">..</span>.<span class=\"token punctuation\">\\</span>my-app<span class=\"token punctuation\">\\</span>package.json\n<span class=\"token punctuation\">[</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token punctuation\">]</span> <span class=\"token number\">11</span>/11 <span class=\"token number\">100</span>%\n\n @testing-library/react       ^14.0.0  →  ^15.0.0\n @testing-library/user-event  ^14.4.3  →  ^14.5.2\n react                        ^18.2.0  →  ^19.0.0\n vite                          ^5.0.0  →   ^6.0.0\n\nRun ncu <span class=\"token parameter variable\">-u</span> to upgrade package.json</code></pre></div>\n<p>El archivo <i>package.json</i> se actualiza ejecutando el comando <i>ncu -u</i>.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ ncu <span class=\"token parameter variable\">-u</span>\nUpgrading <span class=\"token punctuation\">..</span>.<span class=\"token punctuation\">\\</span>my-app<span class=\"token punctuation\">\\</span>package.json\n<span class=\"token punctuation\">[</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token operator\">==</span><span class=\"token punctuation\">]</span> <span class=\"token number\">11</span>/11 <span class=\"token number\">100</span>%\n\n @testing-library/react       ^14.0.0  →  ^15.0.0\n @testing-library/user-event  ^14.4.3  →  ^14.5.2\n react                        ^18.2.0  →  ^19.0.0\n vite                          ^5.0.0  →   ^6.0.0\n\nRun <span class=\"token function\">npm</span> <span class=\"token function\">install</span> to <span class=\"token function\">install</span> new versions.</code></pre></div>\n<p>Ahora es el momento de actualizar las dependencias ejecutando el comando <i>npm install</i>. Sin embargo, las versiones antiguas de las dependencias no son necesariamente un riesgo de seguridad.</p>\n<p>El comando npm <a href=\"https://docs.npmjs.com/cli/audit\">audit</a> se puede utilizar para verificar la seguridad de las dependencias. Compara los números de versión de las dependencias de tu aplicación con una lista de los números de versión de las dependencias que contienen amenazas de seguridad conocidas en una base de datos de errores centralizada.</p>\n<p>Al ejecutar <i>npm audit</i> en el mismo proyecto, se imprime una larga lista de quejas y correcciones sugeridas.\nA continuación se muestra una parte del informe:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">$ patientor npm audit\n\n<span class=\"token operator\">...</span> many lines removed <span class=\"token operator\">...</span>\n\nurl<span class=\"token operator\">-</span>parse  <span class=\"token operator\">&lt;</span><span class=\"token number\">1.5</span><span class=\"token number\">.2</span>\n<span class=\"token literal-property property\">Severity</span><span class=\"token operator\">:</span> moderate\nOpen redirect <span class=\"token keyword\">in</span> url<span class=\"token operator\">-</span>parse <span class=\"token operator\">-</span> https<span class=\"token operator\">:</span><span class=\"token operator\">/</span><span class=\"token operator\">/</span>github<span class=\"token punctuation\">.</span>com<span class=\"token operator\">/</span>advisories<span class=\"token operator\">/</span><span class=\"token constant\">GHSA</span><span class=\"token operator\">-</span>hh27<span class=\"token operator\">-</span>ffr2<span class=\"token operator\">-</span>f2jc\nfix available via <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">npm audit fix</span><span class=\"token template-punctuation string\">`</span></span>\nnode_modules<span class=\"token operator\">/</span>url<span class=\"token operator\">-</span>parse\n\nws  <span class=\"token number\">6.0</span><span class=\"token number\">.0</span> <span class=\"token operator\">-</span> <span class=\"token number\">6.2</span><span class=\"token number\">.1</span> <span class=\"token operator\">||</span> <span class=\"token number\">7.0</span><span class=\"token number\">.0</span> <span class=\"token operator\">-</span> <span class=\"token number\">7.4</span><span class=\"token number\">.5</span>\n<span class=\"token literal-property property\">Severity</span><span class=\"token operator\">:</span> moderate\nReDoS <span class=\"token keyword\">in</span> Sec<span class=\"token operator\">-</span>Websocket<span class=\"token operator\">-</span>Protocol header <span class=\"token operator\">-</span> https<span class=\"token operator\">:</span><span class=\"token operator\">/</span><span class=\"token operator\">/</span>github<span class=\"token punctuation\">.</span>com<span class=\"token operator\">/</span>advisories<span class=\"token operator\">/</span><span class=\"token constant\">GHSA</span><span class=\"token operator\">-</span>6fc8<span class=\"token operator\">-</span>4gx4<span class=\"token operator\">-</span>v693\nReDoS <span class=\"token keyword\">in</span> Sec<span class=\"token operator\">-</span>Websocket<span class=\"token operator\">-</span>Protocol header <span class=\"token operator\">-</span> https<span class=\"token operator\">:</span><span class=\"token operator\">/</span><span class=\"token operator\">/</span>github<span class=\"token punctuation\">.</span>com<span class=\"token operator\">/</span>advisories<span class=\"token operator\">/</span><span class=\"token constant\">GHSA</span><span class=\"token operator\">-</span>6fc8<span class=\"token operator\">-</span>4gx4<span class=\"token operator\">-</span>v693\nfix available via <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">npm audit fix</span><span class=\"token template-punctuation string\">`</span></span>\nnode_modules<span class=\"token operator\">/</span>webpack<span class=\"token operator\">-</span>dev<span class=\"token operator\">-</span>server<span class=\"token operator\">/</span>node_modules<span class=\"token operator\">/</span>ws\nnode_modules<span class=\"token operator\">/</span>ws\n\n<span class=\"token number\">120</span> <span class=\"token function\">vulnerabilities</span> <span class=\"token punctuation\">(</span><span class=\"token number\">102</span> moderate<span class=\"token punctuation\">,</span> <span class=\"token number\">16</span> high<span class=\"token punctuation\">,</span> <span class=\"token number\">2</span> critical<span class=\"token punctuation\">)</span>\n\nTo address issues that <span class=\"token keyword\">do</span> not require attention<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">run</span><span class=\"token operator\">:</span>\n  npm audit fix\n\nTo address all <span class=\"token function\">issues</span> <span class=\"token punctuation\">(</span>including breaking changes<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">run</span><span class=\"token operator\">:</span>\n  npm audit fix <span class=\"token operator\">--</span>force</code></pre></div>\n<p>Después de solo un año, el código está lleno de pequeñas amenazas de seguridad. Afortunadamente, solo hay 2 amenazas críticas. Ejecutemos <i>npm audit fix</i> como sugiere el informe:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">$ npm audit fix\n\n<span class=\"token operator\">+</span> mongoose@<span class=\"token number\">5.9</span><span class=\"token number\">.1</span>\nadded <span class=\"token number\">19</span> packages from <span class=\"token number\">8</span> contributors<span class=\"token punctuation\">,</span> removed <span class=\"token number\">8</span> packages and updated <span class=\"token number\">15</span> packages <span class=\"token keyword\">in</span> <span class=\"token number\">7</span><span class=\"token punctuation\">.</span>325s\nfixed <span class=\"token number\">354</span> <span class=\"token keyword\">of</span> <span class=\"token number\">416</span> vulnerabilities <span class=\"token keyword\">in</span> <span class=\"token number\">20047</span> scanned packages\n  <span class=\"token number\">1</span> <span class=\"token keyword\">package</span> update <span class=\"token keyword\">for</span> <span class=\"token number\">62</span> vulns involved breaking <span class=\"token function\">changes</span>\n  <span class=\"token punctuation\">(</span>use <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">npm audit fix --force</span><span class=\"token template-punctuation string\">`</span></span> to install breaking changes<span class=\"token punctuation\">;</span> or refer to <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">npm audit</span><span class=\"token template-punctuation string\">`</span></span> <span class=\"token keyword\">for</span> steps to fix these manually<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Quedan 62 amenazas porque, por defecto, <i>audit fix</i> no actualiza las dependencias si su número de versión <i>major</i> ha aumentado. Actualizar estas dependencias podría hacer que toda la aplicación dejara de funcionar.</p>\n<p>El origen del error crítico es la librería <a href=\"https://github.com/immerjs/immer\">immer</a></p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">immer  <span class=\"token operator\">&lt;</span><span class=\"token number\">9.0</span><span class=\"token number\">.6</span>\n<span class=\"token literal-property property\">Severity</span><span class=\"token operator\">:</span> critical\nPrototype Pollution <span class=\"token keyword\">in</span> immer <span class=\"token operator\">-</span> https<span class=\"token operator\">:</span><span class=\"token operator\">/</span><span class=\"token operator\">/</span>github<span class=\"token punctuation\">.</span>com<span class=\"token operator\">/</span>advisories<span class=\"token operator\">/</span><span class=\"token constant\">GHSA</span><span class=\"token operator\">-</span>33f9<span class=\"token operator\">-</span>j839<span class=\"token operator\">-</span>rf8h\nfix available via <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">npm audit fix --force</span><span class=\"token template-punctuation string\">`</span></span>\nWill install react<span class=\"token operator\">-</span>scripts@<span class=\"token number\">5.0</span><span class=\"token number\">.0</span><span class=\"token punctuation\">,</span> which is a breaking change</code></pre></div>\n<p>Ejecutar <i>npm audit fix --force</i> actualizaría la versión de la librería, pero también actualizaría <i>react-scripts</i>, lo que podría hacer que el entorno de desarrollo dejara de funcionar. Así que dejaremos las actualizaciones de las librerías para más adelante...</p>\n<p>Una de las amenazas mencionadas en la lista de OWASP es <i>Broken Authentication</i> y <i>Broken Access Control</i>. La autenticación basada en tokens que hemos estado usando es bastante sólida si la aplicación se usa con el protocolo HTTPS de cifrado de tráfico. Al implementar el control de acceso, por ejemplo, se debe recordar no solo verificar la identidad de un usuario en el navegador, sino también en el servidor. Mala seguridad sería evitar que se tomen algunas acciones solo ocultando las opciones de ejecución en el código del navegador.</p>\n<p>En MDN de Mozilla hay una muy buena <a href=\"https://developer.mozilla.org/es/docs/Learn/Server-side/First_steps/Website_security\">guía de seguridad de sitios web</a>, que trae a colación este tema tan importante:</p>\n<picture><img src=\"/static/a7b95baf708b2945f316155b024c062d/5a190/34.png\" alt=\"screenshot de un consejo importante sobre seguridad de MDN\" srcset=\"/static/a7b95baf708b2945f316155b024c062d/772e8/34.png 200w,\n/static/a7b95baf708b2945f316155b024c062d/e17e5/34.png 400w,\n/static/a7b95baf708b2945f316155b024c062d/5a190/34.png 800w,\n/static/a7b95baf708b2945f316155b024c062d/c1b63/34.png 1200w,\n/static/a7b95baf708b2945f316155b024c062d/52576/34.png 1412w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>La documentación de Express incluye una sección sobre seguridad: <a href=\"https://expressjs.com/es/advanced/best-practice-security.html\">Mejores prácticas de producción: seguridad</a>, que vale la pena leer. También se recomienda agregar una librería llamada <a href=\"https://helmetjs.github.io/\">Helmet</a> al backend. Incluye un conjunto de middlewares que eliminan algunas vulnerabilidades de seguridad en aplicaciones Express.</p>\n<p>También vale la pena usar el <a href=\"https://github.com/nodesecurity/eslint-plugin-security\">plugin de seguridad</a> de ESlint.</p>\n<h3>Tendencias actuales</h3>\n<p>Finalmente, echemos un vistazo a la tecnología del mañana (o en realidad ya de hoy), y las direcciones en las que se dirige el desarrollo web.</p>\n<h4>Versiones tipadas de JavaScript</h4>\n<p>El <a href=\"https://developer.mozilla.org/es/docs/Glossary/Dynamic_typing\">tipado dinámico</a> de JavaScript puede producir errores sutiles que solo se descubren durante la ejecución. En la parte 5 mencionamos <a href=\"/es/part5/props_children_y_la_ref_del_componente#prop-types\">PropTypes</a> como forma de añadir comprobaciones de tipos en tiempo de ejecución a las props de los componentes, pero PropTypes ha caído en gran medida en desuso a medida que el ecosistema ha adoptado la <a href=\"https://en.wikipedia.org/wiki/Type_system#Static_type_checking\">comprobación estática de tipos</a>.</p>\n<p><a href=\"https://www.typescriptlang.org/\">TypeScript</a>, desarrollado por Microsoft, se ha convertido en el estándar de facto para JavaScript tipado. Detecta errores de tipo en tiempo de compilación en vez de durante la ejecución, ofrece herramientas excelentes para el editor y ya se utiliza en la mayoría de los proyectos nuevos de React. TypeScript se cubre en la <a href=\"/es/part9\">parte 9</a>.</p>\n<h4>Renderizado en el servidor y React Server Components</h4>\n<p>Los componentes de React no tienen por qué ejecutarse en el navegador. También pueden renderizarse en el <a href=\"https://es.react.dev/reference/react-dom/server\">servidor</a>, que envía HTML ya preparado al cliente en vez de una página vacía que JavaScript deba rellenar. Este <i>server-side rendering</i> (SSR) mejora el tiempo de carga percibido y es importante para la optimización para motores de búsqueda (SEO), ya que los rastreadores ven el contenido completamente renderizado sin tener que ejecutar JavaScript.</p>\n<p>El desarrollo más reciente y significativo son los <a href=\"https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components\">React Server Components</a> (RSC), introducidos en React 18 y ahora parte fundamental de la arquitectura de React. Un componente de servidor se ejecuta exclusivamente en el servidor y nunca se envía al navegador como JavaScript. Puede leer directamente de una base de datos o del sistema de archivos, mantener secretos fuera del bundle del cliente y transmitir su salida al navegador. El navegador recibe estos componentes como datos renderizados, no como código ejecutable. Los <i>componentes de cliente</i>, marcados con <code>'use client'</code>, siguen ejecutándose en el navegador y gestionan la interactividad como antes. En una aplicación RSC, la mayoría de los componentes son componentes de servidor por defecto y solo se utilizan componentes de cliente donde se necesita interacción con el usuario.</p>\n<p><a href=\"https://nextjs.org/\">Next.js</a> se ha convertido en el framework estándar para crear aplicaciones React que necesitan comportamiento del lado del servidor. Su App Router —introducido en Next.js 13— se basa en React Server Components y proporciona enrutamiento basado en archivos, layouts anidados, acciones de servidor para modificar datos y soporte incorporado para la generación estática y la regeneración estática incremental. En 2026, Next.js es la primera opción para cualquier proyecto React en el que importen el SSR, el SEO o las capacidades full stack.</p>\n<h4>Arquitectura de microservicios</h4>\n<p>Durante este curso solo hemos arañado la superficie del lado del servidor. En nuestras aplicaciones teníamos un backend <i>monolítico</i>, es decir, una aplicación que formaba un todo y se ejecutaba en un solo servidor, sirviendo solo unos pocos endpoints de API.</p>\n<p>A medida que la aplicación crece, el enfoque de backend monolítico comienza a tornarse problemático tanto en términos de rendimiento como de mantenibilidad.</p>\n<p>Una <a href=\"https://martinfowler.com/articles/microservices.html\">arquitectura de microservicios</a> es una forma de componer el backend de una aplicación a partir de muchos servicios independientes que se comunican entre sí a través de la red. El propósito de un microservicio individual es encargarse de un todo funcional lógico particular. En una arquitectura de microservicios pura, los servicios no utilizan una base de datos compartida.</p>\n<p>Por ejemplo, la aplicación de lista de blogs podría constar de dos servicios: uno que maneja al usuario y otro que se ocupa de los blogs. La responsabilidad del servicio de usuario sería el registro y la autenticación del usuario, mientras que el servicio de blogs se haría cargo de las operaciones relacionadas con los blogs.</p>\n<p>La siguiente imagen muestra la diferencia entre la estructura de una aplicación basada en una arquitectura de microservicios y una basada en una estructura monolítica más tradicional:</p>\n<picture><img src=\"/static/beecf1d05714ef6a4ac0721fce62d394/5a190/36.png\" alt=\"diagrama de enfoques de microservicios vs tradicional\" srcset=\"/static/beecf1d05714ef6a4ac0721fce62d394/772e8/36.png 200w,\n/static/beecf1d05714ef6a4ac0721fce62d394/e17e5/36.png 400w,\n/static/beecf1d05714ef6a4ac0721fce62d394/5a190/36.png 800w,\n/static/beecf1d05714ef6a4ac0721fce62d394/c1b63/36.png 1200w,\n/static/beecf1d05714ef6a4ac0721fce62d394/ce0a7/36.png 1590w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>El papel del frontend (encerrado por un cuadrado en la imagen) no difiere mucho entre los dos modelos. A menudo existe una <a href=\"http://microservices.io/patterns/apigateway\">API gateway</a> (puerta de enlace API) entre los microservicios y el frontend, que proporciona la ilusión de una API más tradicional de \"todo en el mismo servidor\". <a href=\"https://medium.com/netflix-techblog/optimizing-the-netflix-api-5c9ac715cf19\">Netflix</a>, entre otros, utiliza este tipo de enfoque.</p>\n<p>Las arquitecturas de microservicios surgieron y evolucionaron para las necesidades de las grandes aplicaciones a gran escala de Internet. Amazon marcó la tendencia mucho antes de la aparición del término microservicio. El punto de partida crítico fue un correo electrónico enviado a todos los empleados en 2002 por el CEO de Amazon, Jeff Bezos:</p>\n<blockquote>\n<p>De ahora en adelante, todos los equipos expondrán sus datos y funcionalidad a través de interfaces de servicio.</p>\n<p>Los equipos deben comunicarse entre sí a través de estas interfaces.</p>\n<p>No se permitirá ninguna otra forma de comunicación entre procesos: ningún enlace directo, ninguna lectura directa del almacén de datos de otro equipo, ningún modelo de memoria compartida, ninguna puerta trasera. La única comunicación permitida es a través de llamadas de interfaz de servicio a través de la red.</p>\n<p>No importa qué tecnología uses.</p>\n<p>Todas las interfaces de servicio, sin excepción, deben diseñarse desde cero para ser externalizables. Es decir, el equipo debe planificar y diseñar para poder exponer la interfaz a los desarrolladores del mundo exterior.</p>\n<p>Sin excepciones.</p>\n<p>Cualquiera que no haga esto será despedido. Gracias; ¡que tengas un buen día!</p>\n</blockquote>\n<p>Hoy en día, uno de los mayores precursores en el uso de microservicios es <a href=\"https://www.infoq.com/presentations/netflix-chaos-microservices\">Netflix</a>.</p>\n<p>El uso de microservicios ha ido ganando popularidad hasta convertirse en una especie de <a href=\"https://es.wikipedia.org/wiki/No_hay_balas_de_plata\">bala de plata</a> de hoy en día, que se ofrece como una solución a casi todo tipo de problemas. Sin embargo, hay una serie de desafíos cuando se trata de aplicar una arquitectura de microservicios, y podría tener sentido ir <a href=\"https://martinfowler.com/bliki/MonolithFirst.html\">primero al monolito</a> al hacer inicialmente un backend tradicional que lo abarque todo. O quizás <a href=\"https://martinfowler.com/articles/dont-start-monolith.html\">no</a>. Hay un montón de opiniones diferentes sobre el tema. Ambos enlaces conducen al sitio de Martin Fowler; como podemos ver, incluso los sabios no están completamente seguros de cuál de las formas correctas es la más correcta.</p>\n<p>Desafortunadamente, no podemos profundizar en este importante tema durante este curso. Incluso una mirada superficial al tema requeriría al menos 5 semanas más.</p>\n<h4>Serverless (Sin servidor)</h4>\n<p>Después del lanzamiento del servicio <a href=\"https://aws.amazon.com/lambda/\">Lambda</a> de Amazon a fines de 2014, comenzó a surgir una nueva tendencia en el desarrollo de aplicaciones web: <a href=\"https://serverless.com/\">sin servidor</a>.</p>\n<p>Lo principal acerca de Lambda, y hoy en día también de Google <a href=\"https://cloud.google.com/functions/\">Cloud functions</a>, así como de una <a href=\"https://azure.microsoft.com/en-us/services/functions/\">funcionalidad similar en Azure</a>, es que permite <i>la ejecución de funciones individuales</i> en la nube. Antes, la unidad ejecutable más pequeña en la nube era un <i>proceso único</i>, por ejemplo, un entorno de ejecución que ejecuta un backend de Node.</p>\n<p>Utilizando la <a href=\"https://aws.amazon.com/es/api-gateway/\">API gateway</a> de Amazon es posible crear aplicaciones sin servidor donde las solicitudes a la API HTTP definida obtienen respuestas directamente de las funciones de la nube. Por lo general, las funciones ya operan utilizando datos almacenados en las bases de datos del servicio en la nube.</p>\n<p>Serverless no se trata de que no haya un servidor en las aplicaciones, sino de cómo se define el servidor. El desarrollador de software puede cambiar sus esfuerzos de programación a un mayor nivel de abstracción, pues ya no es necesario definir mediante programación el enrutamiento de solicitudes HTTP, relaciones de bases de datos, etc., debido a que la infraestructura de la nube proporciona todo esto. Las funciones en la nube también se prestan para crear un buen sistema de escalado, por ejemplo, Lambda de Amazon puede ejecutar una gran cantidad de funciones en la nube por segundo. Todo esto ocurre automáticamente a través de la infraestructura y no es necesario iniciar nuevos servidores, etc.</p>\n<h3>Librerías útiles y lecturas adicionales</h3>\n<p>La comunidad de desarrolladores de JavaScript ha creado una gran variedad de librerías útiles. Antes de escribir algo desde cero, siempre merece la pena comprobar si ya existe una solución bien mantenida.</p>\n<p>Puedes aprovechar tus conocimientos de React para desarrollar aplicaciones móviles con <a href=\"https://reactnative.dev/\">React Native</a>, tema que se trata en la <a href=\"/es/part10\">parte 10</a> del curso.</p>\n<p>El curso continúa más allá de la parte 7: la <a href=\"/es/part8\">parte 8</a> cubre GraphQL; la <a href=\"/es/part9\">parte 9</a>, TypeScript; la <a href=\"/es/part10\">parte 10</a>, React Native; la <a href=\"/es/part11\">parte 11</a>, CI/CD; y la <a href=\"/es/part12\">parte 12</a>, contenedores. El contenido completo se encuentra en la <a href=\"/es/#contenido-del-curso\">página del curso</a>.</p>\n<p>Los siguientes recursos externos son buenos lugares para profundizar en patrones de React, calidad del código y el ecosistema en general:</p>\n<ul>\n<li><a href=\"https://www.patterns.dev/\">Patterns.dev</a> trata en profundidad patrones modernos de React y JavaScript. Como colección seleccionada de técnicas específicas de React, <a href=\"https://vasanthk.gitbooks.io/react-bits/\">React bits</a> es un complemento útil.</li>\n<li><a href=\"https://overreacted.io/\">Overreacted</a> es el blog de Dan Abramov, uno de los miembros originales del equipo principal de React. Sus artículos profundizan en las decisiones de diseño y los modelos mentales de React y merece la pena leerlos aunque tengan ya algunos años.</li>\n<li><a href=\"https://kentcdodds.com/blog\">Kent C. Dodds</a> escribe extensamente sobre buenas prácticas de React, pruebas y diseño de componentes. En particular, sus artículos sobre la filosofía de las pruebas han influido en la forma en que la comunidad concibe las pruebas del frontend.</li>\n<li><a href=\"https://alexkondov.com/tao-of-react/\">Tao of React</a> es una guía breve y deliberadamente subjetiva para estructurar aplicaciones React que trata los componentes, el estado, las props y la organización de proyectos de forma pragmática.</li>\n<li><a href=\"https://www.reactiflux.com/\">Reactiflux</a> es una gran comunidad de desarrolladores de React en Discord y un buen lugar para plantear preguntas después de terminar el curso. Muchas librerías de código abierto mantienen allí sus propios canales.</li>\n</ul>\n</div>","frontmatter":{"mainImage":{"publicURL":"/static/2184b1c35920cfc7a09e10660dea04eb/part-7.svg"},"part":7,"letter":"c","lang":"es"}}},"pageContext":{"part":7,"letter":"c","lang":"es"}},"staticQueryHashes":["3128451518"]}