<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Códice | Entradas sobre «react»</title><description>Feed RSS de publicaciones etiquetadas con react</description><link>https://javguerra.github.io/</link><item><title>Ordenando resultados en React</title><link>https://javguerra.github.io/blog/ordenacion-react</link><guid isPermaLink="true">https://javguerra.github.io/blog/ordenacion-react</guid><description>Filtrando el listado de información por distintos criterios y mostrándolo en orden creciente o decreciente.</description><pubDate>Wed, 23 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/dalton.uMLTtW5b_zpaNY.webp&quot; alt=&quot;Ordenación&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#react&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Cuando mostramos un listado con muchos resultados en nuestra web sin un criterio de ordenación, el usuario debe encontrar la información que necesita, lo que requiere tiempo y esfuerzo por su parte. Para atajar este problema podemos incluir un campo de búsqueda, pero aún así, la información aparecerá desordenada. En esta entrada veremos como seleccionar la ordenación de listados de menor a mayor y viceversa, y cómo hacerlo por varios criterios de ordenación alternativamente en nuestra aplicación React.&lt;/p&gt;
&lt;p&gt;El lector deberá conocer el funcionamiento básico de React y JavaScript para poder seguir adecuadamente esta entrada.&lt;/p&gt;
&lt;p&gt;Esta entrada está basada en el proyecto &lt;a href=&quot;/blog/tienda-8-bits&quot;&gt;«Tienda 8 bits»&lt;/a&gt;, y puedes ver su funcionamiento en la &lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;página del proyecto&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Este artículo ha sido publicado también en &lt;a href=&quot;https://ifgeekthen.nttdata.com/s/post/ordenando-resultados-en-react-MCYT76DWYR2JEVBLOOQWIOAIXD7Q&quot;&gt;IfGeekThen&lt;/a&gt;, el blog de NTT Data, el 15 de abril de 2026.&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;el-ejemplo&quot;&gt;El ejemplo&lt;/h1&gt;
&lt;p&gt;En nuestra web, queremos listar una serie de fichas de productos por tres criterios, &lt;strong&gt;modelo de producto&lt;/strong&gt;, &lt;strong&gt;precio&lt;/strong&gt; y &lt;strong&gt;año de fabricación&lt;/strong&gt;, y queremos hacerlo alternativamente, es decir, por uno de entre esos tres criterios de ordenación cada vez.&lt;/p&gt;
&lt;p&gt;La ordenación se hará de menor a mayor, osea, en orden ascendente, y de mayor a menor, en orden descendente. Tomaremos la información de las fichas desde, por ejemplo, una API que debe estar preparada para ello, es decir, que la API pueda devolver los datos solicitados según los parámetros de ordenación necesarios. Pero no me pararé a mostrarlo en esta entrada.&lt;/p&gt;
&lt;p&gt;Los filtros, en la página, tendrán un aspecto parecido a lo que se ve en la imagen:&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Filtros&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/filtros.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;En este caso, el primer filtro de ordenación, el de modelo, es el que está seleccionado, y la ordenación la realiza en orden ascendente. Los otros dos filtros no están activos.&lt;/p&gt;
&lt;h1 id=&quot;la-aplicación&quot;&gt;La aplicación&lt;/h1&gt;
&lt;p&gt;Para este ejercicio, en la página App.jsx o la que usemos para llamar a la ordenación, voy a definir dos &lt;code&gt;useState&lt;/code&gt;, uno que contendrá los filtros de ordenación en un objeto y otro que contendrá el número de la página actual de los resultados paginados (grupos de resultados) que vamos a mostrar.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; useState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ sortmodel: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;currentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; useState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En una aplicación completa deberemos incluir otros useState para, por ejemplo, guardar los datos obtenidos de la consulta a la API, o los criterios de búsqueda de datos… En este ejercicio me limito a incluir sólo los que son operativos para la explicación.&lt;/p&gt;
&lt;p&gt;Dentro del objeto que tendremos en &lt;code&gt;sortData&lt;/code&gt; iremos incluyendo, alternativamente, &lt;code&gt;sortmodel&lt;/code&gt; para filtrar por el modelo, &lt;code&gt;sortprice&lt;/code&gt; para filtrar por el precio, o &lt;code&gt;sortyear&lt;/code&gt; para filtrar por el año. Sólo uno de ellos a la vez. Los valores posibles para cada una de estas propiedades de filtrado serán &lt;code&gt;1&lt;/code&gt; y &lt;code&gt;-1&lt;/code&gt;, siendo 1 el valor que indica ordenación ascendente, y -1 el valor que indica ordenación descendente, que son los valores que acepta nuestra API. Inicalizamos el &lt;code&gt;useState&lt;/code&gt;  &lt;code&gt;sortData&lt;/code&gt; con &lt;code&gt;{ sortmodel: 1 }&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;useEffect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortmodel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortprice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortyear&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sortData;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Preparar los datos para la consulta a la API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Realizar la consulta a la API y obtener (set) los resultados&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, [sortData, currentPage]);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cuando el objeto almacenado en &lt;code&gt;sortData&lt;/code&gt; cambie por la interacción del usuario, al seleccionar mediante un clic otro criterio de ordenación, entrará en juego la función &lt;code&gt;setSortData&lt;/code&gt;, y el contenido dentro de &lt;code&gt;useEffect&lt;/code&gt; se ejecutará, pasando los datos de filtrado &lt;code&gt;sortData&lt;/code&gt; a la petición a la API mediante fetch, axios… Los datos deben ser preparados antes de hacer la consulta, y para ello, deberemos comprobar cual de los tres filtros (sortmodel, sortprice, sortyear) está seleccionado y cuales no (&lt;em&gt;undefined&lt;/em&gt;), e incluir el filtro indicado en la consulta.&lt;/p&gt;
&lt;p&gt;El componente que va a permitir seleccionar el tipo de ordenación se llama &lt;code&gt;Sort&lt;/code&gt;, y esta sería la llamada para renderizarlo en la página:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Sort&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        sortData&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortData}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        setSortData&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{setSortData}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{setCurrentPage}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Por &lt;em&gt;props&lt;/em&gt; le hacemos llegar al componente Sort los datos de filtrado (sortData), la función que establece (set) el filtrado (setSortData) y la función que establece la página actual (setCurrentPage). setCurrentPage es necesario porque cada vez que cambie el filtrado deberemos establecer la página 1 como la página actual, de otra forma los datos obtenidos con el nuevo filtrado se mostrarían confusos para el usuario.&lt;/p&gt;
&lt;h2 id=&quot;el-componente-sort&quot;&gt;El componente Sort&lt;/h2&gt;
&lt;p&gt;El código del componente será el siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SortIcon &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;./SortIcon&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Sort&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortmodel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortprice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortyear&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sortData;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sortName&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ [sortName]: order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;ul&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sortmodel&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, sortmodel)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Modelo &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SortIcon&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortmodel} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sortprice&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, sortprice)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Precio &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SortIcon&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortprice} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sortyear&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, sortyear)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Año &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SortIcon&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortyear} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;ul&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Sort;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Primeramente importo el componente &lt;code&gt;SortIcon&lt;/code&gt; que luego veremos. Éste componente se encargará de mostrar los iconos de ordenación de cada uno de los tres criterios por los que vamos a ordenar el listado.&lt;/p&gt;
&lt;p&gt;Como dije, el componente &lt;code&gt;Sort&lt;/code&gt; recibe por &lt;code&gt;props&lt;/code&gt; tres parámetros &lt;code&gt;{sortData, setSortData, setCurrentPage}&lt;/code&gt; con el dato del tipo de ordenación elegido, la función para fijar la nueva ordenación y la función para fijar la página actual de la paginación de resultados.&lt;/p&gt;
&lt;p&gt;Lo primero que hago es obtener los datos del objeto &lt;code&gt;sortData&lt;/code&gt; recibido por props. Por supuesto, sólo uno de los tres datos va a llegar con un valor. Los otros dos, que no son el criterio de filtrado seleccionado, tendrán valor &lt;em&gt;undefined&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La función &lt;code&gt;handleIcon&lt;/code&gt; será la encargada de efectuar el cambio del filtro de ordenación. Y a cada &lt;code&gt;sortIcon&lt;/code&gt;, en el renderizado, le paso el valor de &lt;code&gt;order&lt;/code&gt;, que contiene el valor de ordenación del filtrado (1 ó -1) que le corresponde.&lt;/p&gt;
&lt;p&gt;Al hacer click en cualquiera de los tres criterios de ordenación en la página, la función &lt;code&gt;handleIcon&lt;/code&gt; dentro de &lt;code&gt;onClick={() =&amp;gt; handleIcon(&quot;nombre_del_filtro&quot;, variable_de_ordenación)}&lt;/code&gt; se ejecuta, con los parámetros &lt;code&gt;&quot;nombre_del_filtro&quot;&lt;/code&gt; y &lt;code&gt;variable_de_ordenación&lt;/code&gt;, lo que permite hacer el cambio en la ordenación, disparando el &lt;code&gt;useEffect&lt;/code&gt; de nuestra aplicación que vimos antes, provocando que los productos listados se actualicen con la nueva ordenación mediante una nueva consulta a la API.&lt;/p&gt;
&lt;h2 id=&quot;la-función-handleicon&quot;&gt;La función handleIcon&lt;/h2&gt;
&lt;p&gt;Aquí es donde se lleva a cabo el cambio de filtrado.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sortName&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ [sortName]: order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función recibe dos parámetros, &lt;code&gt;sortName&lt;/code&gt;, con el nombre del filtro seleccionado en función del icono (SortIcon) en el que se haga clic, y &lt;code&gt;order&lt;/code&gt;, con el valor de ordenación de ese filtro (1 ó -1).&lt;/p&gt;
&lt;p&gt;Con la función &lt;code&gt;setSortData&lt;/code&gt;, que recibí por props, voy a fijar el criterio de ordenación y su valor.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;[sortName]:&lt;/code&gt; dentro del objeto que voy a pasar a &lt;code&gt;setSortData&lt;/code&gt; para cambiar &lt;code&gt;sortData&lt;/code&gt; indico que la propiedad se tiene que llamar como el nombre del filtro recibido en &lt;code&gt;sortName&lt;/code&gt; (que puede ser uno de estos tres: “sortmodel”, “sortprice” o “sortyear”). Con los corchetes consigo que el texto recibido sea el nombre de la propiedad.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;order ? -order : 1&lt;/code&gt; determino el valor de la propiedad del objeto que voy a pasar a &lt;code&gt;setSortData&lt;/code&gt;. Si el valor de order existe, es decir no es &lt;code&gt;undefined&lt;/code&gt;, y por tanto es el criterio de ordenación actual, su valor ahora será el valor alternativo (positivo o negativo) al que ya tiene. Si el valor era 1, ahora será -1. Si era -1, pasará a ser 1. Y en caso de que el valor de &lt;code&gt;order&lt;/code&gt; fuera &lt;code&gt;undefined&lt;/code&gt;, es decir, que no fuese este el filtro por el que estábamos filtrando antes, se establece su valor a 1.&lt;/p&gt;
&lt;p&gt;Como cada vez que empleo &lt;code&gt;setSortData&lt;/code&gt; defino sólo un filtro de ordenación, el resto de filtros tendrá un valor &lt;code&gt;undefined&lt;/code&gt; cuando se renderizen en el componente &lt;code&gt;Sort&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;setCurrentPage(1)&lt;/code&gt; fijo la página de la paginación de resultados a 1.&lt;/p&gt;
&lt;p&gt;Con esta simple función puedo entonces, como dije, seleccionar el filtrado entre uno de los tres filtros posibles, y establecer el criterio de ordenación (ascendente o descendente) del filtro seleccionado.&lt;/p&gt;
&lt;h2 id=&quot;el-componente-sorticon&quot;&gt;El componente SortIcon&lt;/h2&gt;
&lt;p&gt;Este componente es el encargado de mostrar el icono de estado de cada uno de los tres criterios de ordenación en la página.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; SortIcon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v12&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0l-3.75-3.75M17.25 21L21 17.25&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; className&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      viewBox&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 24 24&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; strokeWidth&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stroke&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;currentColor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; strokeLinecap&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; strokeLinejoin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{d} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SortIcon;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Por &lt;em&gt;props&lt;/em&gt;, &lt;code&gt;SortIcon&lt;/code&gt; recibe el parámetro &lt;code&gt;order&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En el renderizado lo que hago es dibujar el icono SVG en función del valor de &lt;code&gt;order&lt;/code&gt;, que puede ser: 1, -1 y &lt;em&gt;undefined&lt;/em&gt;. Para elegir que icono mostrar, cambio el valor de la propiedad &lt;code&gt;d&lt;/code&gt; de la imagen SVG que pinta el icono. La propiedad &lt;code&gt;d&lt;/code&gt; es la única que cambia en los tres iconos elegidos, el de ordenación ascendente (1), descendente (-1) y no seleccionado (&lt;em&gt;undefined&lt;/em&gt;), así que utilizo el mismo código SVG para los tres iconos, y cambio sólo el valor de d en función de su estatus (order).&lt;/p&gt;
&lt;p&gt;Con el operador condicional ternario compruebo si &lt;code&gt;order&lt;/code&gt; es &lt;code&gt;undefined&lt;/code&gt; (!order) y si es así, asigno a &lt;code&gt;d&lt;/code&gt; los datos para pintar el icono de “no seleccionado”. En caso contrario, hago otra comprobación con otro operador condicional ternario, esta vez para conocer si el icono a dibujar es el de ordenación ascendente o descendente, y asignar a &lt;code&gt;d&lt;/code&gt; los datos correspondientes a cada icono.&lt;/p&gt;
&lt;p&gt;Los iconos mostrados en la captura de este ejemplo corresponden a la librería &lt;a href=&quot;https://heroicons.com/&quot;&gt;Heroicons&lt;/a&gt;, descargados en su versión JSX.&lt;/p&gt;
&lt;h1 id=&quot;en-resumen&quot;&gt;En resumen&lt;/h1&gt;
&lt;p&gt;A partir de la interacción del usuario, y gracias al &lt;code&gt;useEffect&lt;/code&gt; que se ejecuta cuando se detecta el cambio, se ha establecido un criterio de ordenación diferente, modificado el aspecto de los botones según este nuevo criterio y, como consecuencia, se ha obtenido un listado actualizado de productos ordenados a través de la API preparada para ello.&lt;/p&gt;
&lt;p&gt;Para lograrlo, se han creado dos estados (&lt;code&gt;sortData&lt;/code&gt; y &lt;code&gt;currentPage&lt;/code&gt;) y un componente &lt;code&gt;Sort&lt;/code&gt; que recibe &lt;code&gt;sortData&lt;/code&gt;, &lt;code&gt;setSortData&lt;/code&gt; y &lt;code&gt;setCurrentPage&lt;/code&gt;. Este componente detecta los clics, cambia el estado de la ordenación en &lt;code&gt;sortData&lt;/code&gt; mediante la función &lt;code&gt;handleIcon&lt;/code&gt; (activando solo un filtro cada vez y alternando entre ascendente y descendente), luego vuelve a la página 1 con &lt;code&gt;setCurrentPage(1)&lt;/code&gt; y muestra el icono apropiado para cada filtro usando el componente &lt;code&gt;SortIcon&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Tomando todo esto como referencia, ya puedes hacer tus propios filtros de ordenación para tu nueva aplicación React.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;Página de ejemplo «Tienda 8 bits»&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/tienda-8-bits&quot;&gt;Información sobre el proyecto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://heroicons.com/&quot;&gt;Heroicons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/dalton.uMLTtW5b_zpaNY.webp"/><category>react</category><category>javascript</category><author>JavGuerra</author></item><item><title>Tienda 8 bits</title><link>https://javguerra.github.io/blog/tienda-8-bits</link><guid isPermaLink="true">https://javguerra.github.io/blog/tienda-8-bits</guid><description>Proyecto de graduación del Bootcamp Full Stack Web Developer</description><pubDate>Fri, 18 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/tienda-8-bits.BGpB2fQx_Znqyrs.webp&quot; alt=&quot;Banner tienda 8 bits&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#formación&lt;/em&gt;, &lt;em&gt;#becas&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#express&lt;/em&gt;, &lt;em&gt;#react&lt;/em&gt;, &lt;em&gt;#mongodb&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#accesibilidad&lt;/em&gt;, &lt;em&gt;#responsive&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Durante el año 2022 cursé el &lt;a href=&quot;/blog/beca-santander-fswd&quot;&gt;Bootcamp de Desarrollo Web Full Stack&lt;/a&gt; que &lt;a href=&quot;https://www.becas-santander.com/es/index.html&quot;&gt;Becas Santander&lt;/a&gt; llevó a cabo en colaboración con &lt;a href=&quot;https://www.universia.net/es/empleo&quot;&gt;Fundación Universia&lt;/a&gt;, &lt;a href=&quot;https://www.indracompany.com/&quot;&gt;Indra&lt;/a&gt; y &lt;a href=&quot;https://www.thebridge.tech/&quot;&gt;The Bridge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;&lt;button&gt;Ir a la aplicación on-line&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El día 17 de noviembre finalizó la formación con un acto de entrega de diplomas on-line en el que tuve ocasión de mostrar mi proyecto final «Tienda 8 bits» junto con Alex, otro de mis compañeros, quien también expuso su proyecto.&lt;/p&gt;
&lt;p&gt;A parte de los compañeros y los profesores, asistieron al evento Alejandra Cuenca y Diego Díaz por parte de The Bridge, Cristina Soriano por Minsait/Indra, y Beatriz Arribas y Carlos Sánchez por Universia.&lt;/p&gt;
&lt;h2 id=&quot;video&quot;&gt;Video&lt;/h2&gt;
&lt;p&gt;El evento se llevó a cabo de forma presencial y on-line, y de él he rescatado el video de mi presentación que comparto a continuación.&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Video de presentación&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/tienda.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/XlswjqhxJZ8&quot;&gt;&lt;button&gt;Ver el video en YouTube&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;descripción-técnica&quot;&gt;Descripción técnica&lt;/h2&gt;
&lt;h3 id=&quot;back-end&quot;&gt;Back end&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Tecnologías empleadas&lt;/strong&gt;: Node.js + Express + MongoDB + Mongoose&lt;br&gt;
&lt;strong&gt;Módulos&lt;/strong&gt;: compression, cors, helmet, dotenv, nodemon, mongoose-paginator-v2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Características destacadas de la API&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emplea módulos ESM.&lt;/li&gt;
&lt;li&gt;Está preparada para el versionado de la API.&lt;/li&gt;
&lt;li&gt;Está preparada para el uso de BBDD MongoDB local o en remoto (config.js).&lt;/li&gt;
&lt;li&gt;Preserva la seguridad del acceso a la API con el uso del módulo helmet.&lt;/li&gt;
&lt;li&gt;Devuelve las rutas de los enlaces a las fotos y logos dinámicamente.&lt;/li&gt;
&lt;li&gt;Cuenta con documentación de la API.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;front-end&quot;&gt;Front end&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Tecnologías empleadas&lt;/strong&gt;: React + Vite, axios, react-router-dom, react-hook-form&lt;br&gt;
&lt;strong&gt;Módulos propios&lt;/strong&gt;: setSpin, inactiveBtn, compareTwoObjects&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Características destacadas de la App&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El diseño es adaptable (responsive) según el dispositivo.&lt;/li&gt;
&lt;li&gt;CSS propio. No usa frameworks.&lt;/li&gt;
&lt;li&gt;Es accesible (revisado con el complemento &lt;a href=&quot;https://wave.webaim.org/&quot;&gt;WAVE&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Utiliza fuentes de Google Font en los títulos para preservar la accesibilidad.&lt;/li&gt;
&lt;li&gt;Implementa el protocolo &lt;a href=&quot;https://ogp.me/&quot;&gt;Open Graph&lt;/a&gt; para la correcta inserción de la web en RRSS.&lt;/li&gt;
&lt;li&gt;Es compatible con Progessive Web Aplication (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Progressive_web_apps&quot;&gt;PWA&lt;/a&gt;) a través de fichero &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Manifest&quot;&gt;manifest.json&lt;/a&gt;, por lo que la página puede ser instalada en dispositivos móviles como una web app.&lt;/li&gt;
&lt;li&gt;Ha sido probada con los navegadores web Firefox y Chrome.&lt;/li&gt;
&lt;li&gt;Tratamiento de imágenes con software libre: Gimp e InkScape.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;fuentes&quot;&gt;Fuentes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Wikipedia&lt;/li&gt;
&lt;li&gt;Enciclopedia «Mi Computer», editorial Delta, 1984.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;licencias&quot;&gt;Licencias&lt;/h3&gt;
&lt;p&gt;Sobre el código fuente: &lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/LICENSE&quot;&gt;GNU GENERAL PUBLIC LICENSE Version 3&lt;/a&gt;&lt;br&gt;
Sobre el contenido de la web: &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0/es/&quot;&gt;(CC) BY-SA 3.0&lt;/a&gt;&lt;br&gt;
Sobre las fotos: Son propiedad de sus respectivos autores.&lt;br&gt;
Sobre las fuentes de letra: &lt;a href=&quot;https://fonts.google.com/&quot;&gt;Google Fonts&lt;/a&gt;&lt;br&gt;
Sobre los iconos: &lt;a href=&quot;https://heroicons.com/&quot;&gt;Heroicons&lt;/a&gt;&lt;br&gt;
Material usado sin ánimo de lucro bajo criterios didácticos y formativos.&lt;/p&gt;
&lt;h3 id=&quot;acceder-a-la-aplicación&quot;&gt;Acceder a la aplicación&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/JavGuerra/tienda-8-bits/0d3d3a968787a438379d003fe31aaede91011e40/qrcode.svg&quot; alt=&quot;Código QR&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;&lt;button&gt;Ir a la aplicación on-line&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;Aplicación on-line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api-tienda8bits.up.railway.app/&quot;&gt;Documentación de la API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/enunciado.pdf&quot;&gt;Enunciado de la práctica en PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits&quot;&gt;Repositorio en GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/XlswjqhxJZ8&quot;&gt;Video de la presentación en YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/presentacion.pdf&quot;&gt;Presentación en PDF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Artículos informativos elaborados por el autor relacionados con esta práctica&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/populate-paginate-fitrado&quot;&gt;Usando populate con paginate y filtrando los resultados&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/rutas-dinamicas-imagenes-mongodb&quot;&gt;Generar enlaces dinámicos de imágenes almacenadas en MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/ordenacion-react&quot;&gt;Ordenando resultados en React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/spinner-loader-asincrono&quot;&gt;Spinner loader asíncrono&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/tienda-8-bits.BGpB2fQx_Znqyrs.webp"/><category>portfolio</category><category>web</category><category>formación</category><category>becas</category><category>node.js</category><category>express</category><category>react</category><category>mongodb</category><category>javascript</category><category>accesibilidad</category><category>responsive</category><author>JavGuerra</author></item></channel></rss>