<?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: Christian Caracach</title>
    <description>The latest articles on DEV Community by Christian Caracach (@ccaracach).</description>
    <link>https://dev.to/ccaracach</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%2F1092681%2Fefbda776-e80e-4a58-9e44-70d13e607dda.jpg</url>
      <title>DEV Community: Christian Caracach</title>
      <link>https://dev.to/ccaracach</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ccaracach"/>
    <language>en</language>
    <item>
      <title>Por qué necesitás React Query</title>
      <dc:creator>Christian Caracach</dc:creator>
      <pubDate>Mon, 13 Nov 2023 01:37:48 +0000</pubDate>
      <link>https://dev.to/ccaracach/por-que-necesitas-react-query-3a1n</link>
      <guid>https://dev.to/ccaracach/por-que-necesitas-react-query-3a1n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Ésta es una traducción del post &lt;a href="https://tkdodo.eu/blog/why-you-want-react-query"&gt;Why You Want React Query&lt;/a&gt; de Dominik Dorfmeister(TkDodo) - 07.11.2023&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No es ningún secreto que me encanta React Query por cómo simplifica la forma en que interactuamos con el estado asíncrono en nuestras aplicaciones React. Y sé que muchos colegas desarrolladores sienten lo mismo.&lt;/p&gt;

&lt;p&gt;A veces, sin embargo, me encuentro con publicaciones que afirman que no necesitas utilizarlo para hacer algo tan "simple" como obtener datos de un servidor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No necesitamos todas las funciones adicionales que React Query ofrece, así que no queremos agregar una biblioteca de terceros cuando podemos simplemente realizar una búsqueda de datos en un useEffect de manera igualmente sencilla.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hasta cierto punto, creo que es un punto válido: React Query te proporciona muchas funciones como almacenamiento en caché, reintentos, sondeos, sincronización de datos, precarga, ... y alrededor de un millón más que irían mucho más allá del alcance de este artículo. Está bien si no los necesitas, pero aún así creo que esto no debería impedirte usar React Query.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Frameworks&lt;br&gt;
Si estás utilizando un marco de trabajo que tiene una solución incorporada para la obtención y mutación de datos, &lt;a href="https://tkdodo.eu/blog/you-might-not-need-react-query"&gt;es posible que no necesites React Query&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entonces, en lugar de eso, analicemos el ejemplo estándar de realizar una búsqueda en un useEffect que surgió recientemente en &lt;a href="https://twitter.com/ken_wheeler/status/1719122802333118557"&gt;Twitter&lt;/a&gt; y profundicemos en por qué podría ser una buena idea utilizar React Query también en esas situaciones:&lt;/p&gt;

&lt;p&gt;fetch-in-useEffect&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si crees que este código es adecuado para casos de uso simples donde no necesitas funciones adicionales, permíteme decirte que identifiqué de inmediato 🐛 5 errores 🪲 escondidos en estas 10 líneas de código.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XFQVuP4I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjljmdfdkc5a67atri78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XFQVuP4I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjljmdfdkc5a67atri78.png" alt="meme de Ésto está bien" width="636" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quizás tómate uno o dos minutos y ve si puedes encontrarlos todos. Esperaré...&lt;/p&gt;

&lt;p&gt;Pista: No es el conjunto de dependencias. Eso está bien.&lt;/p&gt;

&lt;p&gt;1- Condición de Carrera 🏎&lt;br&gt;
Hay razones por las cuales la &lt;a href="https://react.dev/reference/react/useEffect#fetching-data-with-effects"&gt;documentación oficial de React&lt;/a&gt;t recomienda usar un framework o una biblioteca como React Query para la obtención de datos. Mientras que realizar la solicitud de búsqueda puede ser un ejercicio bastante trivial, hacer que ese estado esté disponible de manera predecible en tu aplicación ciertamente no lo es.&lt;/p&gt;

&lt;p&gt;El efecto está configurado de manera que se vuelve a buscar cada vez que cambia la categoría, lo cual es ciertamente correcto. Sin embargo, las respuestas de la red pueden llegar en un orden diferente al que las enviaste. Así que si cambias la categoría de libros a películas y la respuesta de películas llega antes que la respuesta de libros, terminarás con datos incorrectos en tu componente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bV8FZLiH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4zo5ervyrrzah0ybhr8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bV8FZLiH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4zo5ervyrrzah0ybhr8.png" alt="Línea de tiempo que comienza a obtener libros, luego obtiene películas. Las películas se resuelven más rápido, por lo que establecemos los datos de películas (setData(movies)) antes de establecer los datos de libros (setData(books))." width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al final, te quedará un estado inconsistente: tu estado local indicará que has seleccionado películas, pero los datos que estás representando son en realidad de libros.&lt;/p&gt;

&lt;p&gt;La documentación de React dice que podemos solucionar esto con una función de limpieza y un booleano de ignorar, así que hagámoslo:&lt;/p&gt;

&lt;p&gt;ignore-flag&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo que sucede ahora es que la función de limpieza del efecto se ejecuta cuando cambia la categoría, estableciendo la bandera local de "ignorar" en true. Si después de eso llega una respuesta de búsqueda, ya no llamará a setState. Muy fácil.&lt;/p&gt;

&lt;p&gt;2- Estado de carga 🕐&lt;br&gt;
No está presente en absoluto. No tenemos forma de mostrar una interfaz de usuario pendiente mientras se realizan las solicitudes, ni para la primera ni para las solicitudes posteriores. Entonces, ¿agreguemos eso?&lt;/p&gt;

&lt;p&gt;loading-state&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- Estado vacío 🗑️&lt;br&gt;
Inicializar los datos con un array vacío parece una buena idea para evitar tener que verificar indefiniciones(undefined) todo el tiempo, pero ¿qué pasa si recuperamos datos para una categoría que aún no tiene entradas, y de hecho recibimos un array vacío? No tendríamos forma de distinguir entre "sin datos aún" y "ningún dato en absoluto". El estado de carga que acabamos de introducir ayuda, pero aún es mejor inicializar con indefinido(undefined):&lt;/p&gt;

&lt;p&gt;empty-state&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- Los datos y el error no se reinician cuando cambia la categoría 🔄&lt;br&gt;
Tanto los datos como el error son variables de estado separadas, y no se reinician cuando cambia la categoría. Esto significa que si una categoría falla y cambiamos a otra que se recupera con éxito, nuestro estado será:&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;datosDeLaCategoriaActual&lt;/span&gt;
&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errorDeLaCategoriaAnterior&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado dependerá de cómo rendericemos JSX en función de este estado. Si verificamos primero el error, renderizaremos la interfaz de usuario de error con el mensaje antiguo, aunque tengamos datos válidos:&lt;/p&gt;

&lt;p&gt;error-first&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&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;data&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;item&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;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si verificamos primero los datos, tenemos el mismo problema si la segunda solicitud falla. Si siempre renderizamos tanto el error como los datos, también estamos mostrando información potencialmente desactualizada. 😔&lt;/p&gt;

&lt;p&gt;Para solucionar esto, debemos restablecer nuestro estado local cuando cambia la categoría:&lt;/p&gt;

&lt;p&gt;reset-state&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&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="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5- Se ejecutará dos veces en StrictMode 🔥🔥&lt;br&gt;
Bueno, esto es más una molestia que un error, pero definitivamente es algo que sorprende a los nuevos desarrolladores de React. Si tu aplicación está envuelta en , React llamará intencionalmente &lt;a href="https://react.dev/reference/react/StrictMode#fixing-bugs-found-by-re-running-effects-in-development"&gt;tu efecto dos veces&lt;/a&gt; en el modo de desarrollo para ayudarte a encontrar errores como funciones de limpieza faltantes.&lt;/p&gt;

&lt;p&gt;Si quisiéramos evitar eso, tendríamos que agregar otra "solución de contorno con ref", lo cual no creo que valga la pena.&lt;/p&gt;

&lt;p&gt;Bonus: Manejo de errores 🚨&lt;br&gt;
No incluí esto en la lista original de errores porque tendrías el mismo problema con React Query: fetch no rechaza los errores HTTP, así que tendrías que verificar res.ok y lanzar un error tú mismo.&lt;/p&gt;

&lt;p&gt;error-handling&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&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="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Por qué Fetch no rechaza las respuestas de error&lt;br&gt;
Si deseas obtener más información sobre por qué fetch se comporta de esa manera, echa un vistazo a este &lt;a href="https://twitter.com/kettanaito"&gt;excelente artículo de Artem Zakharchenko&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nuestro pequeño useEffect hook de "solo queremos obtener datos, ¿qué tan difícil puede ser?" se convirtió en un gran desorden de código espagueti 🍝 tan pronto como tuvimos que considerar casos especiales y la gestión del estado. Entonces, ¿cuál es la lección aquí?&lt;/p&gt;

&lt;p&gt;La obtención de datos es simple.&lt;br&gt;
La gestión asíncrona del estado no lo es.&lt;br&gt;
Y aquí es donde entra React Query, porque React Query NO es una biblioteca de obtención de datos, es un gestor de estado asíncrono. Entonces, cuando dices que no lo necesitas para hacer algo tan simple como obtener datos de un punto final, en realidad tienes razón: incluso con React Query, necesitas escribir el mismo código de obtención que antes.&lt;/p&gt;

&lt;p&gt;Pero aún lo necesitas para hacer que ese estado esté disponible de manera predecible en tu aplicación de la manera más fácil posible. Porque seamos honestos, no escribí ese código de booleano de ignorar antes de usar React Query, y probablemente tú tampoco lo hiciste. 😉&lt;/p&gt;

&lt;p&gt;Con React Query, el código anterior se convierte en:&lt;/p&gt;

&lt;p&gt;react-query&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&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;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&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="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto abarca aproximadamente el 50% del código espagueti mencionado anteriormente, y más o menos la misma cantidad que el fragmento original y con errores. Y sí, esto aborda automáticamente todos los errores que encontramos:&lt;/p&gt;

&lt;p&gt;🐛 Errores&lt;br&gt;
🏎️ No hay condición de carrera porque el estado siempre se almacena según su entrada (categoría).&lt;br&gt;
🕐 Obtienes estados de carga, datos y error de forma gratuita, incluyendo uniones discriminadas a nivel de tipo.&lt;br&gt;
🗑️ Los estados vacíos están claramente separados y se pueden mejorar aún más con funciones como placeholderData.&lt;br&gt;
🔄 No obtendrás datos ni errores de una categoría anterior a menos que optes por ello.&lt;br&gt;
🔥 Las múltiples solicitudes se deduplican de manera eficiente, incluidas aquellas provocadas por StrictMode.&lt;/p&gt;

&lt;p&gt;Entonces, si aún piensas que no quieres usar React Query, me gustaría desafiarte a probarlo en tu próximo proyecto. Apuesto a que no solo terminarás con un código más resistente a casos especiales, sino también más fácil de mantener y ampliar. Y una vez que pruebes todas las funciones que ofrece, es probable que nunca mires hacia atrás.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Query.gg 🔮&lt;br&gt;
He estado trabajando en un nuevo curso oficial sobre React Query junto con &lt;a href="https://ui.dev/"&gt;ui.dev&lt;/a&gt;. Este curso te brindará una comprensión de los principios fundamentales tanto de cómo funciona React Query bajo el capó como de cómo escribir código de React Query que escala. Si te gusta el contenido que he estado creando hasta ahora, te encantará &lt;a href="https://query.gg/?r=dom"&gt;query.gg&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cn2Z0MWa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qw5xa6zdvjrm440hjdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cn2Z0MWa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qw5xa6zdvjrm440hjdf.png" alt="Query.gg - El curo oficial de React Query" width="800" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bonus: Cancelación&lt;br&gt;
Muchas personas en Twitter mencionaron la falta de cancelación de solicitudes en el fragmento original. No creo que eso sea necesariamente un error, solo una característica faltante. Por supuesto, React Query también tiene esto cubierto con un cambio bastante sencillo:&lt;/p&gt;

&lt;p&gt;cancelation&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;function&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;signal&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;fetch&lt;/span&gt;&lt;span class="p"&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;endpoint&lt;/span&gt;&lt;span class="p"&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;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;signal&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&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="c1"&gt;// Return JSX based on data and error state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simplemente toma la señal que recibes en queryFn, pásala a fetch y las solicitudes se abortarán automáticamente cuando cambie la categoría. 🎉&lt;/p&gt;

&lt;p&gt;Eso es todo por hoy. No dudes en contactarme en &lt;a href="https://twitter.com/tkdodo"&gt;Twitter&lt;/a&gt; si tienes alguna pregunta, o simplemente deja un comentario abajo. ⬇️&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>ReactJs vs React Native: Resumen, diferencias clave, ventajas y desventajas</title>
      <dc:creator>Christian Caracach</dc:creator>
      <pubDate>Fri, 06 Oct 2023 20:31:53 +0000</pubDate>
      <link>https://dev.to/ccaracach/reactjs-vs-react-native-resumen-diferencias-clave-ventajas-y-desventajas-1jmh</link>
      <guid>https://dev.to/ccaracach/reactjs-vs-react-native-resumen-diferencias-clave-ventajas-y-desventajas-1jmh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Ésta es una traducción del post &lt;a href="https://brocoders.com/blog/reactjs-vs-react-native/"&gt;ReactJs vs React Native: Overview, key difference, pros and cons&lt;/a&gt; de Yevhen Cheshchevyi - 22.01.2022&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o0OEPfEb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2smvso7jg6yz1jyxwfyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o0OEPfEb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2smvso7jg6yz1jyxwfyc.png" alt="Image description" width="720" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React es una de las bibliotecas de JavaScript más populares para construir aplicaciones web. Es utilizada por grandes empresas de tecnología de todo el mundo, incluyendo Instagram, Facebook, Netflix y otros. React Native es un framework basado en React que ayuda a construir aplicaciones móviles multiplataforma.&lt;/p&gt;

&lt;p&gt;Según la &lt;a href="https://insights.stackoverflow.com/survey/2020"&gt;encuesta anual de StackOverflow&lt;/a&gt;, un recurso importante para programadores, React ocupa el segundo lugar en una lista de los frameworks más populares entre los desarrolladores web. Supera ampliamente a sus competidores directos, Vue.js y Angular.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es React.js?
&lt;/h2&gt;

&lt;p&gt;React.js es una biblioteca de JavaScript para construir aplicaciones web que cambian su estado sin recargar las páginas. Es una solución perfecta para construir interfaces de usuario complejas con una gran cantidad de contenido dinámico que se transforma a medida que los usuarios interactúan con los elementos de la página.&lt;/p&gt;

&lt;p&gt;En 2011, el ingeniero de Facebook Jordan Valke creó FaxJs, un prototipo de React. El código fuente de la biblioteca se hizo público en 2013. Desde entonces, React ha evolucionado desde una herramienta prometedora para optimizar aplicaciones web hasta convertirse en un componente de desarrollo indispensable.&lt;/p&gt;

&lt;p&gt;Una de sus principales características es que una aplicación impulsada por React puede renderizarse tanto en el lado del servidor como en el lado del cliente cuando sea necesario. Cuando los desarrolladores de React idearon un mecanismo para simplificar la renderización en el lado del servidor, la biblioteca ganó popularidad. Este enfoque ayuda a crear aplicaciones de alto rendimiento con una buena optimización.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q5glXvOa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcfwvk3nqt1y2e8srcfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q5glXvOa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcfwvk3nqt1y2e8srcfz.png" alt="Image description" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Beneficios de React.js
&lt;/h2&gt;

&lt;p&gt;Uno de los principales beneficios de React.js es que hace que el desarrollo sea más eficiente al permitir que el programador controle el ciclo de representación de los componentes de la aplicación. React es ideal para crear una interfaz dinámica que responde rápidamente a las acciones del usuario.&lt;/p&gt;

&lt;p&gt;La primera característica importante de React es un enfoque declarativo activamente utilizado. Un desarrollador puede describir el comportamiento de los elementos en función de ciertas acciones realizadas por un usuario y, de esta manera, controlar el flujo, en contraposición al enfoque imperativo.&lt;/p&gt;

&lt;p&gt;El segundo principio es la utilización de componentes. Una interfaz se compone de "bloques de construcción" que se pueden transformar según se desee. Un programador describe los componentes utilizando la sintaxis JSX, que es similar a HTML pero se considera más legible que JavaScript.&lt;/p&gt;

&lt;p&gt;El tercer elemento clave es el DOM virtual, lo que significa que durante el trabajo, la interacción se realiza con una copia más ligera del DOM. Cuando es necesario actualizar el árbol DOM, se compara con la copia virtual y solo se representan los elementos alterados. Para los usuarios, esto se traduce en una representación más rápida y un menor consumo de recursos del dispositivo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lsHCyanV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fka6q5xbhlpbor5ubed4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lsHCyanV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fka6q5xbhlpbor5ubed4.png" alt="Image description" width="720" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React es utilizado por muchas empresas grandes para construir poderosas aplicaciones web que pueden ser constantemente mejoradas y mantenidas a lo largo del tiempo.&lt;/p&gt;

&lt;p&gt;Beneficios clave de React desde la perspectiva del cliente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alto rendimiento. Los elementos cambian su estado al instante ya que el sistema actualiza objetos específicos en lugar de toda la página.&lt;/li&gt;
&lt;li&gt;Reutilización de componentes. Los desarrolladores pueden tomar elementos necesarios de bibliotecas de terceros de componentes predefinidos y ensamblar una interfaz bloque por bloque. Esto incluye elementos de diseño de materiales de Material-UI, componentes del framework de Bootstrap de React-Bootstrap y muchos otros. Esto es beneficioso para los clientes, ya que los programadores gastan menos tiempo construyendo la interfaz de usuario.&lt;/li&gt;
&lt;li&gt;Mantener los beneficios de las aplicaciones clásicas. La mayoría de los frameworks modernos ofrecen renderización en el lado del servidor. React puede imitar el comportamiento disponible en las aplicaciones clásicas por defecto, lo cual es positivo.&lt;/li&gt;
&lt;li&gt;Trabajar con una gran cantidad de componentes. Si es necesario, una aplicación web basada en React puede optimizarse para manejar grandes cantidades de datos, aunque requerirá bastante tiempo.&lt;/li&gt;
&lt;li&gt;Un gran número de herramientas de automatización. Los desarrolladores tienen &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; para encontrar errores en el código JS, un conjunto de herramientas proporcionado por &lt;a href="https://github.com/testing-library/react-testing-library"&gt;React Testing Library&lt;/a&gt; para pruebas, etc.&lt;/li&gt;
&lt;li&gt;La principal ventaja de usar React desde un punto de vista empresarial es su alta popularidad. No es un problema encontrar un desarrollador, y también es posible reemplazar al contratista si es necesario. Un nuevo programador entenderá la esencia del producto, analizará el enfoque del colega y se pondrá en marcha.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Trampas y desafíos
&lt;/h2&gt;

&lt;p&gt;Si un cliente necesita un sitio con un gran número de páginas y planea promocionarlo en los motores de búsqueda, elegir React como núcleo conducirá inevitablemente a la necesidad de la renderización en el servidor. Esto complica el desarrollo y afecta el costo final del proyecto.&lt;/p&gt;

&lt;p&gt;Al mismo tiempo, React tiene una documentación bien diseñada. Está respaldado por una comunidad activa de desarrolladores, que es una de las más grandes del mundo. Los miembros de la comunidad siempre están dispuestos a ayudar, y las soluciones para las tareas más comunes se describen en recursos populares.&lt;/p&gt;

&lt;p&gt;Otra desventaja está asociada con un pequeño número de componentes no estándar. Si necesita algo complicado, tendrá que crearlo usted mismo. Y el tiempo de desarrollo aumentará significativamente si hay muchos de estos componentes incluidos en la interfaz.&lt;/p&gt;

&lt;p&gt;Las bibliotecas de componentes de React son tanto una pérdida como una ganancia. Los desarrolladores deben integrar cada "bloque de construcción" en un "edificio terminado"; es decir, no se trata solo de agregar algunos "ladrillos" nuevos, sino de convertirlos en parte de un gran ecosistema. A veces, esto lleva mucho tiempo.&lt;/p&gt;

&lt;p&gt;El principal inconveniente es que React es simplemente un conjunto de componentes diferentes. Los desarrolladores pueden elegir su propio conjunto de tecnología, y cada una de las herramientas vendrá con ventajas y desventajas.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es React Native?
&lt;/h2&gt;

&lt;p&gt;React Native es un marco para el desarrollo de aplicaciones móviles multiplataforma, basado en React.js. Es un producto creado por programadores de Facebook y puesto a disposición de la comunidad en 2015.&lt;/p&gt;

&lt;p&gt;Los programadores que conocen JavaScript y la sintaxis de React pueden dominar fácilmente el marco y construir aplicaciones para teléfonos inteligentes tanto en Android como en iOS sin necesidad de dividir la tarea en múltiples equipos de desarrollo.&lt;/p&gt;

&lt;p&gt;Vale la pena señalar en esta reseña de React Native que una aplicación consta de dos elementos principales: el núcleo de JS y una parte nativa que se ejecutan en paralelo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gs47c17r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/41nxfgbtljh7nsv8xjuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gs47c17r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/41nxfgbtljh7nsv8xjuy.png" alt="Image description" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Beneficios de React Native
&lt;/h2&gt;

&lt;p&gt;La principal ventaja de React Native es su núcleo en forma de React, aunque la interfaz se muestra como si estuviera creada con la ayuda de herramientas nativas para Android e iOS. Los usuarios no notarán la diferencia entre aplicaciones basadas en Swift y React Native.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://brocoders.com/blog/top-examples-of-react-native-apps-in-2023/"&gt;Muchos gigantes de la tecnología&lt;/a&gt; utilizan RN para combinar código con soluciones nativas. Una parte del código puede escribirse en Java para Android o Swift para iOS e integrarse en el código de React Native.&lt;/p&gt;

&lt;p&gt;La diferencia global entre React y React Native es que el primero crea el DOM en un navegador, mientras que RN se integra en la arquitectura de aplicaciones móviles basadas en Android e iOS.&lt;/p&gt;

&lt;p&gt;Los principales beneficios desde una perspectiva empresarial son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enorme popularidad. React Native se hizo público hace solo seis años, pero desde entonces han aparecido muchos componentes que simplifican el desarrollo.&lt;/li&gt;
&lt;li&gt;Desarrollo simultáneo. El cliente recibe una aplicación para dos de los principales sistemas operativos móviles de una sola vez. No es necesario pagar por dos equipos separados.&lt;/li&gt;
&lt;li&gt;Nivel de productividad suficiente. Las aplicaciones basadas en React Native están a la par con sus contrapartes nativas cuando se trata de productos con funcionalidad básica.&lt;/li&gt;
&lt;li&gt;Arquitectura modular. Permite dividir una aplicación en módulos intercambiables, lo que hace que el proceso de creación de un producto sea universal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aAN_pRO4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lfromjx7na4ij6q25zzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aAN_pRO4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lfromjx7na4ij6q25zzh.png" alt="Image description" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El análisis instantáneo de cambios, el tiempo reducido de actualización de aplicaciones y otros beneficios hacen de React Native una de las mejores herramientas para construir productos para Android e iOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trampas y Desventajas
&lt;/h2&gt;

&lt;p&gt;RN es adecuado para aplicaciones con lógica compleja que requieren integración con el hardware del dispositivo, pero solo si participan desarrolladores que utilizan tecnologías nativas. Si necesita importar contactos o utilizar Bluetooth, puede usar una biblioteca nativa para eso de la comunidad de RN, sin embargo, cuando se necesita personalización, será bastante difícil implementarla sin conocer la parte nativa. Sin embargo, no hay una mejor alternativa que RN cuando se necesitan interfaces rápidas basadas en API predefinidas.&lt;/p&gt;

&lt;p&gt;Además de lo anterior, React Native tiene varias otras desventajas, a saber, aplicaciones grandes. Si crea productos basados en bibliotecas nativas para Android e iOS, el archivo de instalación será menos intensivo en recursos. Esto se debe a que RN agrega sus propios assets al paquete de la aplicación.&lt;/p&gt;

&lt;p&gt;El principal riesgo para las empresas es la falta de estabilidad garantizada. Google y Apple proporcionan soporte a largo plazo para aplicaciones construidas con bibliotecas nativas. Sin embargo, si Facebook deja de invertir en React Native, un producto impulsado por RN puede dejar de funcionar.&lt;/p&gt;

&lt;p&gt;Comparar React Native vs. React.js solo tiene sentido si un cliente no comprende cuál es la opción adecuada para un proyecto en particular. Estas son herramientas relacionadas que resuelven el mismo problema de diferentes maneras. El marco de JS está diseñado para crear aplicaciones web, y RN está dirigido al desarrollo para dispositivos móviles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZDhoMmcb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8gjnk4br55gc558vqy8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZDhoMmcb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8gjnk4br55gc558vqy8.png" alt="Plataformas de desarrollo móvil multiplataforma utilizadas por desarrolladores de todo el mundo en 2019-2020, según Statista" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React.js reúne tecnología y React Native puede formar parte de aplicaciones con código nativo. Sin embargo, la integración de RN en una aplicación nativa es relevante principalmente para empresas grandes o proyectos específicos. En este escenario, se realizarán cálculos complejos utilizando funciones del sistema, mientras que la representación de la interfaz de usuario se realizará mediante React.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React Query y React Context</title>
      <dc:creator>Christian Caracach</dc:creator>
      <pubDate>Mon, 28 Aug 2023 00:26:34 +0000</pubDate>
      <link>https://dev.to/ccaracach/react-query-y-react-context-gk4</link>
      <guid>https://dev.to/ccaracach/react-query-y-react-context-gk4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Ésta es una traducción del post &lt;a href="https://tkdodo.eu/blog/react-query-and-react-context"&gt;"React Query and React Context"&lt;/a&gt; de Dominik Dorfmeister (TkDodo) - 22.07.2023&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una de las mejores características de React Query es que puedes usar una consulta donde quieras en tu árbol de componentes: Tu componente &lt;strong&gt;&lt;/strong&gt; puede obtener sus propios datos, colocados en el mismo lugar donde los necesitas:&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;function&lt;/span&gt; &lt;span class="nx"&gt;ProductTable&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;productQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useProductQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/table&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorMessage&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;productQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SkeletonLoader&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para mí, esto es genial porque hace que el &lt;strong&gt;ProductTable&lt;/strong&gt; esté desacoplado e independiente, es responsable de leer sus propias dependencias: los datos de los productos. Si ya están en la caché, perfecto, simplemente los leeremos. Si no es así, iremos a buscarlos. Y podemos ver patrones similares surgir con los Componentes del Servidor de React. Ellos también nos permiten obtener datos directamente dentro de nuestros componentes. Ya no hay divisiones arbitrarias entre componentes con estado y sin estado, o entre componentes inteligentes y tontos.&lt;/p&gt;

&lt;p&gt;Poder obtener datos directamente en un componente, donde lo necesitas, es inmensamente útil. Literalmente podemos tomar el componente &lt;strong&gt;ProductTable&lt;/strong&gt; y moverlo a cualquier lugar de nuestra aplicación, y simplemente funcionará. El componente es muy resistente al cambio, que es la razón principal por la cual abogo por acceder a tu consulta directamente donde sea necesario (a través de un hook personalizado), tanto en el punto 10: &lt;a href="https://tkdodo.eu/blog/react-query-as-a-state-manager"&gt;React Query como gestor de estado&lt;/a&gt;, como en el punto 21: &lt;a href="https://tkdodo.eu/blog/thinking-in-react-query"&gt;Pensando en React Query&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sin embargo, no es una solución infalible, ya que conlleva compromisos. Esto no debería ser sorprendente, porque al final del día, todo implica compromisos. Pero, ¿qué estamos intercambiando exactamente aquí?&lt;/p&gt;

&lt;h2&gt;
  
  
  Siendo autosuficiente
&lt;/h2&gt;

&lt;p&gt;Para que un componente sea autónomo, significa que debe manejar casos en los que los datos de la consulta no están disponibles todavía, en particular: los estados de carga y error. Esto no es un gran problema para nuestro componente &lt;strong&gt;&lt;/strong&gt;, porque muy a menudo, cuando se carga por primera vez, en realidad mostrará ese &lt;strong&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pero hay muchas otras situaciones en las que solo queremos leer información de algunas partes de nuestra consulta, donde sabemos que la consulta ya se ha utilizado más arriba en el árbol. Por ejemplo, podríamos tener una &lt;strong&gt;userQuery&lt;/strong&gt; que contiene información sobre el usuario que ha iniciado sesión:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useUserQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fetchUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="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;useCurrentUserQuery&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUserId&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;useUserQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probablemente utilizaremos esta consulta bastante temprano en nuestro árbol de componentes, para verificar qué derechos tiene el usuario que ha iniciado sesión, y esto podría determinar si realmente podemos ver la página o no. Es información esencial que queremos en todas partes de nuestra página.&lt;/p&gt;

&lt;p&gt;Ahora más abajo en el árbol, podríamos tener un componente que quiera mostrar el &lt;strong&gt;nombre de usuario&lt;/strong&gt;, que podemos obtener del gancho &lt;strong&gt;useCurrentUserQuery&lt;/strong&gt;:&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;function&lt;/span&gt; &lt;span class="nx"&gt;UserNameDisplay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUserQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por supuesto, TypeScript no nos dejará hacerlo, porque los &lt;strong&gt;datos&lt;/strong&gt; podrían ser potencialmente indefinidos. Pero nosotros ya sabemos: no puede ser indefinido, porque en nuestra situación, &lt;strong&gt;UserNameDisplay&lt;/strong&gt; no se renderizará sin que la consulta ya se haya iniciado más arriba en el árbol.&lt;/p&gt;

&lt;p&gt;Ese es un pequeño dilema. ¿Queremos simplemente silenciar a TS aquí y hacer &lt;strong&gt;data!.userName&lt;/strong&gt;, porque sabemos que estará definido? ¿Optamos por la seguridad y hacemos &lt;strong&gt;data?.userName&lt;/strong&gt; (lo cual es posible aquí, pero puede no ser tan fácil de lograr en otras situaciones)? ¿Agregamos simplemente una protección: &lt;strong&gt;if (!data) return null&lt;/strong&gt;? ¿O añadimos manejo adecuado de carga y errores a las 25 ubicaciones en las que llamamos a &lt;strong&gt;useCurrentUserQuery&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Para ser honesto, creo que todas esas formas son un tanto subóptimas. No quiero llenar mi base de código con comprobaciones que "nunca deberían ocurrir" (según mi conocimiento actual). Pero tampoco quiero ignorar TypeScript, porque (como es habitual), TS tiene razón.&lt;/p&gt;

&lt;h2&gt;
  
  
  Una dependencia implícita
&lt;/h2&gt;

&lt;p&gt;Nuestro problema surge del hecho de que tenemos una dependencia implícita: una dependencia que solo existe en nuestra mente, en nuestro conocimiento de la estructura de la aplicación, pero que no es visible en el propio código.&lt;/p&gt;

&lt;p&gt;A pesar de que sabemos que podemos llamar con seguridad a &lt;strong&gt;useCurrentUserQuery&lt;/strong&gt; sin tener que comprobar si los datos no están definidos, ningún análisis estático puede verificar esto. Nuestros compañeros de trabajo podrían no saberlo. Yo mismo podría no saberlo dentro de 3 meses.&lt;/p&gt;

&lt;p&gt;La parte más peligrosa es que podría ser cierto ahora, pero podría dejar de serlo en el futuro. Podemos decidir renderizar otra instancia de &lt;strong&gt;UserNameDisplay&lt;/strong&gt; en algún lugar de nuestra aplicación, donde es posible que no tengamos datos de usuario en la caché, o donde podríamos tener datos de usuario en la caché condicionalmente, por ejemplo, si hemos visitado una página diferente antes.&lt;/p&gt;

&lt;p&gt;Esto es completamente opuesto al componente &lt;strong&gt;&lt;/strong&gt;: en lugar de ser resistente al cambio, se vuelve propenso a errores en las refactorizaciones. No esperaríamos que el componente &lt;strong&gt;UserNameDisplay&lt;/strong&gt; se rompiera solo porque movemos algunos componentes aparentemente no relacionados...&lt;/p&gt;

&lt;h2&gt;
  
  
  Hacerlo explícito
&lt;/h2&gt;

&lt;p&gt;La solución es, por supuesto, hacer que la dependencia sea explícita. Y no hay mejor manera de hacerlo que con &lt;strong&gt;React Context&lt;/strong&gt;:&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto de React
&lt;/h2&gt;

&lt;p&gt;Existe un mito bastante extendido sobre el Contexto de React, así que aclaremos esto: No, el Contexto de React no es un administrador de estado. Puede convertirse en una solución aparentemente buena para la gestión de estado cuando se combina con &lt;strong&gt;useState&lt;/strong&gt; o &lt;strong&gt;useReducer&lt;/strong&gt;, pero para ser honesto, nunca me ha gustado realmente este enfoque, ya que he tenido situaciones problemáticas como estas demasiado a menudo:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1495072479118864398-326" src="https://platform.twitter.com/embed/Tweet.html?id=1495072479118864398"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1495072479118864398-326');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1495072479118864398&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Entonces, lo más probable es que estés mejor utilizando una herramienta dedicada. &lt;a href="https://twitter.com/acemarke"&gt;Mark Erikson&lt;/a&gt;, el mantenedor de Redux y autor de publicaciones de blog muy extensas, tiene un buen artículo sobre ese tema: &lt;a href="https://blog.isquaredsoftware.com/2021/01/context-redux-differences/"&gt;Respuestas en Blog: Por qué el Contexto de React no es una herramienta de "gestión de estado" (y por qué no reemplaza a Redux)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mi tuit ya lo menciona: el Contexto de React es una herramienta de inyección de dependencias. Te permite definir qué "cosas" necesita tu componente para funcionar, y cualquier componente padre es responsable de proporcionar esa información.&lt;/p&gt;

&lt;p&gt;Esto es conceptualmente lo mismo que el prop-drilling, que es el proceso de pasar props a través de múltiples capas. El Contexto te permite hacer lo mismo: tomar algunos valores y pasarlos como props a los hijos, excepto que puedes evitar algunas capas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ew9foDPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlvus3gykh3rc6nk2ztw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ew9foDPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlvus3gykh3rc6nk2ztw.png" alt="Árbol de componentes que muestra la transferencia de props a través de dos componentes vs. la transferencia de contexto donde el nieto puede leerlo directamente" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con el contexto, simplemente te saltas al intermediario. En nuestro ejemplo de &lt;strong&gt;useCurrentUserQuery&lt;/strong&gt;, puede ayudarnos a hacer que esa dependencia sea explícita: en lugar de leer &lt;strong&gt;useCurrentUserQuery&lt;/strong&gt; directamente en todos los componentes donde queremos evitar la comprobación de disponibilidad de datos, lo leemos desde el Contexto de React. Y ese contexto será llenado por el componente padre que realmente realiza la primera comprobación:&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;const&lt;/span&gt; &lt;span class="nx"&gt;CurrentUserContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CreateContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;useCurrentUserContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CurrentUserContext&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;CurrentUserContextProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;currentUserQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUserQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentUserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SkeletonLoader&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentUserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorMessage&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentUserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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="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;CurrentUserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentUserQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;children&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;/CurrentUserContext.Provider&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;Aquí, tomamos la &lt;strong&gt;currentUserQuery&lt;/strong&gt; y colocamos los datos resultantes en el Contexto de React, si existen (eliminando los estados de carga y error de antemano). Luego podemos leer desde ese contexto de manera segura en nuestros componentes hijos, por ejemplo, en el componente &lt;strong&gt;UserNameDisplay&lt;/strong&gt;:&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;function&lt;/span&gt; &lt;span class="nx"&gt;UserNameDisplay&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUserContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con eso, hemos convertido nuestra dependencia implícita (sabemos que los datos se han obtenido más arriba en el árbol) en una dependencia explícita. Siempre que alguien vea &lt;strong&gt;UserNameDisplay&lt;/strong&gt;, sabrá que necesitan tener los datos proporcionados desde &lt;strong&gt;CurrentUserContextProvider&lt;/strong&gt;. Esto es algo que puedes tener en cuenta al refactorizar. Si cambias dónde se renderiza el Proveedor, también sabrás que afectará a todos los componentes hijos que utilicen ese contexto. Esto es algo que no puedes saber cuando un componente solo utiliza una consulta, porque las consultas suelen ser globales en toda tu aplicación, y los datos podrían o no existir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agradando a TypeScript
&lt;/h2&gt;

&lt;p&gt;A pesar de todo, TypeScript aún no estará muy contento, porque el Contexto de React está diseñado para funcionar incluso sin un Proveedor, en cuyo caso te proporcionará el valor predeterminado del Contexto, que en nuestro caso es nulo. Dado que nunca queremos que &lt;strong&gt;useCurrentUserContext&lt;/strong&gt; funcione en una situación en la que estemos fuera de un Proveedor, podemos agregar una invariante a nuestro hook personalizado:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUserContext&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;currentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CurrentUserContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CurrentUserContext: No value provided&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este método asegura que fallaremos de manera rápida y con un buen mensaje de error si alguna vez accedemos accidentalmente a &lt;strong&gt;useCurrentUserContext&lt;/strong&gt; en el lugar equivocado. Y con esto, TypeScript inferirá el valor "&lt;strong&gt;User&lt;/strong&gt;" para nuestro hook personalizado, por lo que podemos usarlo de manera segura y acceder a sus propiedades.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sincronización de Estado
&lt;/h2&gt;

&lt;p&gt;Podrías estar pensando: ¿No es esto una "sincronización de estado" - copiar un valor de React Query y ponerlo en otro método de distribución de estado?&lt;/p&gt;

&lt;p&gt;La respuesta es: ¡No, no lo es! La única fuente de verdad sigue siendo la consulta (query). No hay forma de cambiar el valor de contexto aparte del Proveedor (Provider), que siempre reflejará los datos más recientes que tiene la consulta. Nada se copia aquí y nada puede desincronizarse. Pasar &lt;strong&gt;datos&lt;/strong&gt; desde React Query como una propiedad (prop) a un componente hijo tampoco es una "sincronización de estado", y dado que el contexto es similar a la transmisión de propiedades (prop drilling), tampoco es una "sincronización de estado".&lt;/p&gt;

&lt;h2&gt;
  
  
  Cascadas de Solicitudes
&lt;/h2&gt;

&lt;p&gt;Nada está exento de desventajas, y esta técnica tampoco lo está. Específicamente, podría crear cascadas de solicitudes en la red, ya que el árbol de componentes se detendrá en su renderización (se "suspende") en el Proveedor (Provider), por lo que los componentes secundarios no se renderizarán y no podrán realizar solicitudes a la red, incluso si no están relacionados.&lt;/p&gt;

&lt;p&gt;Principalmente consideraría este enfoque para los datos que son obligatorios para mi sub-árbol: la información del usuario es un buen ejemplo, ya que de todos modos podríamos no saber qué renderizar sin esos datos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suspense
&lt;/h2&gt;

&lt;p&gt;Hablando sobre Suspense: Sí, puedes lograr una arquitectura similar con React Suspense, y sí, tiene la misma desventaja: posibles cascadas de solicitudes, de las cuales ya he hablado en el punto #17: &lt;a href="https://tkdodo.eu/blog/seeding-the-query-cache"&gt;Alimentando la Caché de Consultas (Query Cache)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Un problema es que en la versión principal actual (v4), usar "&lt;strong&gt;suspense: true&lt;/strong&gt;" en tu consulta (query) no estrechará el tipo de &lt;strong&gt;datos&lt;/strong&gt;, porque todavía hay formas de desactivar la consulta y evitar que se ejecute.&lt;/p&gt;

&lt;p&gt;Sin embargo, en la versión v5, habrá un gancho explícito llamado "&lt;strong&gt;useSuspenseQuery&lt;/strong&gt;", donde los datos están garantizados para estar definidos una vez que el componente se renderiza. Con eso, podemos hacer:&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;function&lt;/span&gt; &lt;span class="nx"&gt;UserNameDisplay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSuspenseQuery&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y TypeScript estará contento al respecto. 🎉&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Cómo “Reactcionar” - Kent C. Dodds - 3.11.2021</title>
      <dc:creator>Christian Caracach</dc:creator>
      <pubDate>Mon, 21 Aug 2023 00:49:18 +0000</pubDate>
      <link>https://dev.to/ccaracach/como-reactcionar-kent-c-dodds-3112021-36bl</link>
      <guid>https://dev.to/ccaracach/como-reactcionar-kent-c-dodds-3112021-36bl</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V2EvVbY5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dj6v7796si9es7fc6szf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V2EvVbY5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dj6v7796si9es7fc6szf.png" alt="Photo by Artem Sapegin" width="720" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ésta es una traducción del post original &lt;a href="https://kentcdodds.com/blog/how-to-react"&gt;How To React&lt;/a&gt; por &lt;a href="https://kentcdodds.com/"&gt;Kent C. Dodds.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La mejor manera de aprender React es… honestamente, es diferente para todos. Pero aquí hay algunos consejos útiles de alguien que le ha enseñado React a decenas (¿cientos?) de miles de desarrolladores/as.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstracción
&lt;/h2&gt;

&lt;p&gt;Empecemos hablando acerca de la Abstracción. Aquí hay un ejemplo de abstracción de &lt;a href="https://youmightnotneedjquery.com/"&gt;youmightnotneedjquery.com&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// $(el).toggleClass(className);

function toggleClass(el, className) {
  if (el.classList) {
    el.classList.toggle(className)
  } else {
    var classes = el.className.split(' ')
    var existingIndex = -1
    for (var i = classes.length; i--; ) {
      if (classes[i] === className) existingIndex = i
    }

    if (existingIndex &amp;gt;= 0) {
      classes.splice(existingIndex, 1)
    } else {
      classes.push(className)
    }

    el.className = classes.join(' ')
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muy útil. Pero aquí está el truco … Si tu no necesitas darle soporte a IE8, entonces puedes cambiar ésto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// $(el).toggleClass(className)

function toggleClass(el, className) {
  el.classList.toggle(className)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo que, honestamente, es una abstracción que no debería existir en absoluto… el.classList.toggle(className) es suficiente en sí mismo.&lt;/p&gt;

&lt;p&gt;Así que, ésto es lo que necesitás saber sobre una abstracción antes de usarlo en el flujo de trabajo de tu aplicación:&lt;/p&gt;

&lt;p&gt;¿Cuál es el beneficio de ésta abstracción?&lt;/p&gt;

&lt;p&gt;¿Cuál es el costo de ésta abstracción?&lt;/p&gt;

&lt;p&gt;Si no sabés éstas cosas, entonces corrés el riesgo de pagar el costo de solucionar un problema que no tenés. ¡Un costo sin beneficio no es negocio!&lt;/p&gt;

&lt;p&gt;Una parte importante de entender los costos y beneficios es “sentir” el dolor del problema que ésta abstracción resuelve. Por eso es importante aprender React y su ecosistema en el orden correcto para estar seguro de que no no estás sobrepasado por aprender demasiado al mismo tiempo y usar las abstracciones efectivamente.&lt;/p&gt;

&lt;p&gt;Para mas de ésto, chequéa &lt;a href="https://kentcdodds.com/blog/aha-programming"&gt;“AHA Programming”&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Una nota… ¿Solo querés jugar con cosas? ¿Solo querés enviar cosas? Eso es totalmente genial. Solamente reconocé que no conocés los alcances de React y eso puede jugarte en contra en el futuro. Si el futuro no te importa tanto, ¡entonces no te preocupes!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Empezando con Javascript + JS Moderno
&lt;/h2&gt;

&lt;p&gt;Una de las cosas que amo de React es “cuán Javascript es”. Si podés construir una simple aplicación con Javascript regular y las APIs del DOM, entonces vas a entender mucho mejor los beneficios de React. También vas a ser mucho más efectivo usando React, porque honestamente, el 90% de ser efectivo con React es entender buen JavaScript. Para ésto, te sugiero leer mi publicación &lt;a href="https://kentcdodds.com/blog/javascript-to-know-for-react"&gt;“Javascript to know for React”&lt;/a&gt;. También echa un vistazo a &lt;a href="https://javascript30.com/"&gt;javascript30.com &lt;/a&gt;(gratuito) y &lt;a href="https://beginnerjavascript.com/"&gt;beginnerjavascript.com&lt;/a&gt; (pago), ambos de &lt;a href="https://twitter.com/wesbos"&gt;Wes Bos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Además, conocer las características del JavaScript Moderno irá muy lejos. Debido a que JSX necesita un compilador, la mayoría de los desarrolladores/as React dan por sentadas las características/compiladores del Javascript moderno. Asi que la mayoría de los tutoriales van a asumir que tu tienes una comprensión básica de las características modernas de Javascript. Para eso, les sugiero mi Workshop &lt;a href="https://www.youtube.com/playlist?list=PLV5CVI1eNcJgUA2ziIML3-7sMbS7utie5"&gt;“ES6 and Beyond”&lt;/a&gt; (free) que es una grabación de un taller que di en PayPal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Luego, vamos a aprender React
&lt;/h2&gt;

&lt;p&gt;Demasiado material “para principiantes” de React empieza con JSX y un montón de herramientas. React en sí mismo es sorprendentemente simple (&lt;a href="https://react.dev/"&gt;y la documentación es muy buena, sobre todo la Beta&lt;/a&gt;). &lt;a href="https://epicreact.dev/why-i-love-react/"&gt;Lo que amo de React es su simplicidad&lt;/a&gt;. Tristemente, todo alrededor de él puede volverse complicado y puede ser difícil de saber donde están los límites entre React y las herramientas/librerías que se usan con él. Es por ésto que creé “The Beginner’s Guide to React” totalmente gratis en &lt;a href="https://egghead.io/signup"&gt;Egghead.io&lt;/a&gt;. Empieza con todo en el archivo index.html, lo que creo que es importante. No necesitas ninguna herramienta para usar React. He construido proyectos reales con ésta aproximación para una rápida iteración y despliegue. Francamente, no puedo pensar en una forma más rápida de construir ese tipo de aplicaciones simples, y ésto te permite evitar una gran cantidad de innecesaria complejidad y llegar a construir y entregar aplicaciones rápidamente. Podés aprender más sobre ésta aproximación en mi publicación &lt;a href="https://kentcdodds.com/blog/super-simple-start-to-react"&gt;“Super Simple Start to React”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La última lección de mi curso gratuito de egghead te muestra cómo usar CodeSandbox.io para crear tu aplicación completamente en el navegador y descargarla a tu computadora a una aplicación create-react-app.&lt;/p&gt;

&lt;p&gt;¡No necesitas nada instalado para llegar muy lejos! Y una vez que lo hagas, puedes avanzar mucho sin tener que configurar ninguna herramienta. Conozco varias empresas que desarrollan su aplicación con create-react-app.&lt;/p&gt;

&lt;p&gt;Además, tengo una gran cantidad de contenido relacionado con React en &lt;a href="https://kentcdodds.com/blog?q=react"&gt;mi blog&lt;/a&gt; 😅&lt;/p&gt;

&lt;p&gt;Si buscas el camino rápido para aprender React, no busques más allá de &lt;a href="https://epicreact.dev/"&gt;EpicReact.Dev&lt;/a&gt;. Te enseñará todo lo que hace mi Guía para principiantes de React y MUCHO más. EpicReact puede ser tu compañero desde el inicio de tu viaje con React hasta convertirte en un jefe completo en esto. Y lo hace de manera tan efectiva gracias a su enfoque basado en ejercicios. Pasarás MUCHO más tiempo con tus dedos en el teclado aplicando lo que estás aprendiendo que lo que cualquier curso en línea típico te dará. No te pierdas EpicReact.Dev.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencias y npm
&lt;/h2&gt;

&lt;p&gt;Una vez que hayas decidido que no quieres escribir tu propia versión de cada componente que uses, puedes empezar a investigar las dependencias. Hay un MONTON de componentes por ahí y aquí es donde realmente debes comenzar a hacer preguntas como “cuál es el costo” y “cuál es el beneficio”. Trata de no agregar una dependencia hasta después de “sentir el dolor” que se supone que resuelve. Te hará más efectivo usando esa dependencia.&lt;/p&gt;

&lt;p&gt;Te sugiero que leas &lt;a href="https://docs.npmjs.com/"&gt;la documentación de npm&lt;/a&gt; en una tarde. En serio, hazlo. Hay información realmente valiosa allí.&lt;/p&gt;

&lt;p&gt;Además, cuando comiences a usar dependencias, querrás aprender a importarlas. Tengo una charla llamada &lt;a href="https://www.youtube.com/watch?v=kTlcu16rSLc&amp;amp;list=PLV5CVI1eNcJgNqzNwcs4UKrlJdhfDjshf&amp;amp;index=24"&gt;“More than you wanto to know about ES6 Modules”&lt;/a&gt; que probablemente encuentres llena de información útil sobre la sintaxis de los módulos ES.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remix
&lt;/h2&gt;

&lt;p&gt;Es hora de ser serios sobre la construcción de una aplicación en el mundo real. No importa lo que planees construir con React en la web, estarás bien servido si usas &lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt; como tu framework de elección. Me ha permitido construir éste sitio web con un excelente rendimiento y manteniendo un código fantástico que amo trabajar.&lt;/p&gt;

&lt;p&gt;Para aprender Remix, recomiendo &lt;a href="https://remix.run/docs/en/1.19.3"&gt;la documentación oficial&lt;/a&gt;. También tengo algún &lt;a href="https://kentcdodds.com/blog?q=remix"&gt;contenido de Remix en mi blog&lt;/a&gt; que podría ser útil para ti.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gestión de estado
&lt;/h2&gt;

&lt;p&gt;La mayor parte de la gestión típica del estado será administrada por Remix, pero para el estado de la interfaz de usuario (estado que no se persiste en un backend), tendras que comprender cómo gestionar el estado dentro de React.&lt;/p&gt;

&lt;p&gt;Cuando aprendiste React, aprendiste sobre la API useState. Probablemente también aprendiste sobre &lt;a href="https://legacy.reactjs.org/docs/lifting-state-up.html"&gt;Lifting State Up&lt;/a&gt;. En realidad, esto puede llevarte muy lejos con React y te animo a seguir haciéndolo mientras puedas. Eventualmente, es posible que comiences a tener algún problema con “el prop-drilling”. Lo sabrás cuando lo sientas. Cuando esto suceda, te sugiero que leas mi publicación &lt;a href="https://kentcdodds.com/blog/application-state-management-with-react"&gt;“Application State Management”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;React es una biblioteca de gestión del estado de la aplicación y no necesita Redux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estilo de componentes
&lt;/h2&gt;

&lt;p&gt;Honestamente, no puedo dejar de recomendar &lt;a href="https://tailwindcss.com/"&gt;Tailwind&lt;/a&gt;. Una vez que tu aplicación tenga más de unas pocas cientos de líneas de CSS, encontrará que Tailwind puede simplificar realmente las cosas conceptualmente para ti. Es “un framework de CSS con prioridad a las utilidades para construir rápidamente diseños personalizados”.&lt;/p&gt;

&lt;p&gt;Eso dicho, &lt;a href="https://kentcdodds.com/blog/how-remix-makes-css-clashes-predictable"&gt;Remix tiene un mecanismo fantástico para cargar (y descargar!!) CSS en una base por ruta,&lt;/a&gt; por lo que puede ser capaz de manejar solo escribir CSS regular por un tiempo antes de necesitar algo como Tailwind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Y además…
&lt;/h2&gt;

&lt;p&gt;Desde aquí te sugiero que te sumerjas más profundamente en React. Tengo &lt;a href="https://egghead.io/courses/react-class-component-patterns"&gt;mi curso de Patrones avanzados&lt;/a&gt; de componentes de React en egghead.io que puede darte mucha información realmente buena (pero puede obtener una versión más actualizada de este contenido en EpicReact.dev de todos modos, por lo que te sugiero que lo tomes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Espero que esto te dé (y a sus amigos) un camino para cómo aprender React y dónde comenzar cuando se construyen aplicaciones de React. Agregar abstracciones a tu aplicación demasiado temprano las hace menos flexibles, por lo que generalmente seguiría este patrón al construir aplicaciones. ¡Buena suerte!&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Bienvenida</title>
      <dc:creator>Christian Caracach</dc:creator>
      <pubDate>Mon, 21 Aug 2023 00:31:36 +0000</pubDate>
      <link>https://dev.to/ccaracach/bienvenida-13am</link>
      <guid>https://dev.to/ccaracach/bienvenida-13am</guid>
      <description>&lt;p&gt;Mi nombre es Christian. Tengo 32 años y soy de Unquillo, Córdoba (Argentina). Hace un tiempo que soy Desarrollador Frontend para una compañía que se llama VelaONE.&lt;br&gt;
Siempre quise tener un blog, pero me di cuenta que mi habilidades son nulas en la escritura de contenido. Simplemente no me sale. Pero hace poco me di cuenta que quizás no puedo escribir, pero puedo traducir artículos que están en inglés.&lt;br&gt;
Ésto lo descubrí un día en el que estaba leyendo &lt;a href="https://kentcdodds.com/blog"&gt;el blog de Kent C. Dodds&lt;/a&gt; y me encontré con ésta leyenda .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uew3i0Aa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nz0zitv2iansq3v1isqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uew3i0Aa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nz0zitv2iansq3v1isqv.png" alt="Botón que dice add translation en el blog de Kent C. Dodds" width="498" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dije “eu, en serio nadie le traduce los blogposts a Kent C. Dodds?” — “Lo voy a hacer yo”.&lt;br&gt;
Cuento con la experiencia de haber contribuido con la traducción de unos cuantos ejercicios de FreeCodeCamp (de las primeras dos certificaciones). Asi que por qué no…&lt;br&gt;
En éste blog voy a traducir artículos (del inglés al español-argentino) que a mí me interesen sobre programación. Seguro va a estar más enfocado a React y todo su ecosistema, pero no descarto traducir artículos relacionados a CSS, a Javascript, al mundo IT en general.&lt;br&gt;
Pero antes de terminar tengo que sincerarme y hacer dos avisos MUY importantes:&lt;br&gt;
1 — No soy un traductor, no soy profesor de inglés, no tengo ninguna titulación en eso. Las traducciones no van a ser perfectas, si querés corregirme algun error, bienvenido sea, mandame un mail buena onda a &lt;a href="mailto:christiancaracach@gmail.com"&gt;christiancaracach@gmail.com&lt;/a&gt;&lt;br&gt;
2 — Está bueno leer artículos traducidos al español (español argentino), pero no te olvides que en éste rubro, mientras más inglés sepas, mejor, así que también intentá leer los originales asi vas practicando.&lt;br&gt;
Muchas gracias por su atención, que lo disfruten.&lt;/p&gt;

</description>
      <category>welcome</category>
      <category>firstpost</category>
    </item>
  </channel>
</rss>
