<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Ezequiel Castellanos - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Ezequiel Castellanos - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 08:28:21 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/ezequiel_caste/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Cómo escribir código limpio: consejos y mejores prácticas (manual completo) ]]>
                </title>
                <description>
                    <![CDATA[ ¡Hola a todos! En este manual vamos a hablar sobre cómo escribir código "limpio". Es un tema que solía confundirme un poco cuando comenzaba como programador, y encuentro que tiene muchas matices e interpretaciones posibles. Por lo tanto, en este artículo vamos a hablar sobre lo que el término "código ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-escribir-codigo-limpio-consejos-y-mejores-practicas-manual-completo/</link>
                <guid isPermaLink="false">64872d0d9764040891b7de91</guid>
                
                    <category>
                        <![CDATA[ código liimpio ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Mon, 31 Jul 2023 00:05:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/07/pexels-ken-tomita-389819.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-write-clean-code/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Write Clean Code – Tips and Best Practices (Full Handbook)</a>
      </p><p>¡Hola a todos! En este manual vamos a hablar sobre cómo escribir código "limpio". Es un tema que solía confundirme un poco cuando comenzaba como programador, y encuentro que tiene muchas matices e interpretaciones posibles.</p><p>Por lo tanto, en este artículo vamos a hablar sobre lo que el término "código limpio" significa, por qué es importante, cómo podemos evaluar si el código base está limpia o no. También vas a aprender algunas mejores prácticas y convenciones que puedes seguir para hacer que tu código sea más limpio.</p><p>¡Vamos!</p><h1 id="tabla-de-contenido">Tabla de contenido</h1><ul><li>¿<a href="#importancia">Qué significa escribir "código limpio" y por qué debería importarme?</a></li><li><a href="#evaluar">¿Cómo puedo evaluar si una base de código está limpia o no?</a></li><li><a href="#consejos">Consejos y Convenciones para Escribir Código Limpio</a></li><li><a href="#eficacia">Eficacia, Eficiencia y Simplicidad</a></li><li><a href="#formato">Formato y Sintaxis</a></li><li><a href="#nombres">Denominación</a></li><li><a href="#claridad">Concisión vs Claridad</a></li><li><a href="#reusabilidad">Reusabilidad</a></li><li><a href="#flujo">Flujo Claro de Ejecución</a></li><li><a href="#principio">Principio de Responsabilidad Única</a></li><li><a href="#fuente">Tener una "Fuente Única de la Verdad"</a></li><li><a href="#exponer">Expón y Consume los Datos que Necesitas</a></li><li><a href="#modularizacion">Modularización</a></li><li><a href="#carpetas">Estructura de Carpetas</a></li><li><a href="#documentacion">Documentación</a></li><li><a href="#terminando">Terminando</a></li></ul><!--kg-card-begin: html--><h2 id="importancia">¿Qué significa escribir "código limpio" y por qué debería importarme?</h2><!--kg-card-end: html--><p>Código limpio es un término usado para describir código de computadoras que es fácil de leer, entender y mantener. Código limpio se escribe de una manera que lo hace simple, conciso y expresivo. Sigue un conjunto de convenciones, estándares y prácticas que lo hacen fácil de leer y seguir.</p><p>El código limpio es libre de complejidad, redundancias y otros hedores de código ("code smells") y &nbsp;anti-patrones que pueden hacerlo difícil de mantener, depurar y modificar.</p><p>No puedo exagerar la importancia del código limpio. Cuando el código es fácil de leer y entender, es más fácil para los desarrolladores trabajar en el código base. Esto puede llevar a incrementar la productividad y una reducción de errores.</p><p>También, cuando el código es fácil de mantener, se asegura que el código base puede ser mejorado y actualizado con el tiempo. Esto es especialmente importante para proyectos a largo plazo donde el código tiene que ser mantenido y actualizado por años venideros.</p><!--kg-card-begin: html--><h2 id="evaluar">¿Cómo puedo evaluar si una base de código está limpia o no?</h2><!--kg-card-end: html--><p>Puedes evaluar el código limpio en una variedad de maneras. Buena documentación, formato consistente y una base de código bien organizada, son indicadores de código limpio.</p><p>Las revisiones de código también pueden ayudar a identificar posibles problemas y asegurar que el código siga las mejores prácticas y convenciones.</p><p>El testing también es un aspecto importante del código limpio. Ayuda a asegurarnos que el código está funcionando como es esperado y puede detectar errores temprano.</p><p>Existen varias herramientas, prácticas y convenciones que puedes implementar para asegurar una base de código limpia. Al implementar estas herramientas y prácticas, los desarrolladores pueden crear una base de código que sea fácil de leer, entender y mantener.</p><p>También es importante recordar que hay una cantidad inevitable de subjetividad relacionada con este tema, y que hay distintas opiniones y consejos allí afuera. Lo que puede parecer limpio y asombroso para una persona o un proyecto, podría no ser así para otra persona u otro proyecto.</p><p>Sin embargo, existen algunas convenciones generales que podemos seguir para lograr código más limpio, así que vamos a eso ahora.</p><!--kg-card-begin: html--><h2 id="consejos">consejos y convenciones para escribir código limpio</h2><!--kg-card-end: html--><!--kg-card-begin: html--><h2 id="eficacia">Eficacia, Eficiencia y Simplicidad</h2><!--kg-card-end: html--><p>Siempre que necesito pensar sobre cómo implementar una nueva característica a la base de código ya existente, o cómo abordar la solución de un problema específico, siempre priorizo estas tres simples cosas.</p><h3 id="eficacia">Eficacia</h3><p>Primero, nuestro código tiene que ser <strong>eficaz</strong>, lo que significa que debería resolver el problema que se supone que debe resolver. Por supuesto que esta es la expectativa más básica que podemos tener para nuestro código, pero si nuestra implementación en realidad no funciona, es inútil pensar en otra cosa.</p><h3 id="eficiencia">Eficiencia</h3><p>Segundo, una vez que sabemos que nuestro código resuelve el problema, deberíamos verificar si lo hace eficientemente. ¿El programa corre utilizando una cantidad razonable de recursos en términos de tiempo y espacio? ¿Puede correr más rápido con menos espacio?</p><p>La complejidad algorítmica es algo que deberías estar al tanto para poder evaluar esto. </p><p>Para ampliar la eficiencia, aquí hay dos ejemplos de una función que calcula la suma de todos los números en un arreglo.</p><pre><code class="language-javascript">// Ejemplo ineficiente
function sumArrayInefficient(array) {
  let sum = 0;
  for (let i = 0; i &lt; array.length; i++) {
    sum += array[i];
  }
  return sum;
}</code></pre><p>Esta implementación de la función <code>sumArrayInefficient</code> itera sobre el arreglo usando un bucle <code>for</code> y suma cada elemento a la variable <code>sum</code>. Es una solución válida, pero no es muy eficiente porque requiere iterar sobre el arreglo completo, sin importar su tamaño.</p><pre><code class="language-javascript">// Ejemplo eficiente
function sumArrayEfficient(array) {
  return array.reduce((a, b) =&gt; a + b, 0);
}</code></pre><p>Esta implementación de la función <code>sumArrayEfficient</code> utiliza el método <code>reduce</code> para sumar los elementos del arreglo. El método <code>reduce</code> aplica una función a cada elemento del arreglo y acumula el resultado. En este caso, la función simplemente suma cada elemento al acumulador, el cual comienza en 0.</p><p>Esta es una solución más eficiente, ya que sólo requiere una única iteración sobre el arreglo y realiza la operación sumatoria sobre cada elemento a medida que avanza.</p><h3 id="simplicidad"><strong><strong>Simpli</strong>cidad</strong></h3><p>Y por último viene la simplicidad. Esto es lo más difícil de evaluar porque es subjetivo, depende de la persona que lea el código. Pero algunas pautas que podemos seguir son:</p><ol><li>¿Puedes entender fácilmente lo que hace el programa en cada línea?</li><li>¿Las funciones y variables tienen nombres que representan claramente sus responsabilidades?</li><li>¿El código tiene sangrado y espaciado correcto con el mismo formato a lo largo de la base de código?</li><li>¿Hay documentación disponible para el código? Se usan comentarios para explicar partes complejas del programa?</li><li>¿Qué tan rápido puedes identificar en qué parte de la base de código están ciertas características del programa? ¿Puedes eliminar/agregar nuevas características sin la necesidad de modificar varias otras partes del código?</li><li>¿El código sigue un enfoque modular, con diferentes características separadas en componentes?</li><li>¿Se reutiliza el código cuando es posible?</li><li>¿Se siguen las mismas decisiones de arquitectura, diseño e implementación, por igual a lo largo de la base de código?</li></ol><p>Al seguir y priorizar estos tres conceptos de eficacia, eficiencia y simplicidad, siempre vamos a tener pautas para seguir cuando estemos pensando sobre cómo implementar una solución. Ahora extendamos sobre algunas de las pautas que pueden ayudarnos a simplificar nuestro código.</p><!--kg-card-begin: html--><h2 id="formato">Formato y Sintaxis</h2><!--kg-card-end: html--><p>Usar formato y sintaxis consistente a lo largo de la base de código es un aspecto importante de escribir código limpio. Esto es porque el formato y sintaxis consistente hace que el código sea más legible y fácil de entender. </p><p>Cuando el código es consistente, los desarrolladores pueden identificar fácilmente patrones y entender cómo funciona el código, lo que hace más fácil la depuración, mantenimiento y actualización de la base de código con el tiempo. La consistencia también ayuda a reducir errores, ya que asegura que todos los desarrolladores estén siguiendo las mismas normas y convenciones.</p><p>Algunas de las cosas que debemos pensar en relación con el formato y sintaxis son:</p><ul><li><strong>Espaciado y sangrado</strong></li></ul><pre><code class="language-javascript">// mal espaciado y sangrado
const myFunc=(number1,number2)=&gt;{
const result=number1+number2;
return result;
}

// buen espaciado y sangría
const myFunc = (number1, number2) =&gt; {
    const result = number1 + number2
    return result
}
</code></pre><p>Aquí tenemos un ejemplo de una misma función, una hecha sin sangría ni espaciado, y la otra debidamente espaciada y sangrados. Podemos ver que la segunda es claramente más fácil de leer.</p><ul><li><strong>Sintaxis consistente</strong></li></ul><pre><code class="language-javascript">// Función de flecha, sin punto y coma, sin no return
const multiplyByTwo = number =&gt; number * 2

// Función, punto y comas, return
function multiplyByThree(number) {
    return number * 3;
}</code></pre><p>De nuevo, aquí tenemos implementadas funciones muy parecidas con sintaxis diferente. La primera es una función de flecha, sin punto y coma, y sin return, mientras que la otra es una función común que usa punto y coma y un return.</p><p>Ambas funcionan y están muy bien, pero deberíamos apuntar a siempre usar el mismo sintaxis para operaciones similares, ya que se vuelve más uniforme y legible a lo largo de la base de código.</p><p>Los linters y formateadores de código son excelentes herramientas que podemos usar en nuestros proyectos para automatizar las convenciones de sintaxis y formatos en nuestra base de código. </p><p><strong>Convenciones de Mayúsculas y Minúsculas consistentes</strong></p><pre><code class="language-javascript">// camelCase
const myName = 'John'
// PascalCase
const MyName = 'John'
// snake_case
const my_name = 'John'</code></pre><p>Lo mismo va para la convención de mayúsculas y minúsculas que elijamos seguir. &nbsp;Todas éstas funcionan, pero tenemos que apuntar a usar de manera consistente la misma a lo largo de nuestro proyecto.</p><!--kg-card-begin: html--><h2 id="nombres">Denominación</h2><!--kg-card-end: html--><p>Nombrar variables y funciones de manera clara y descriptiva es un aspecto importante de escribir código limpio. Esto ayuda a mejorar la legibilidad y mantenibilidad de la base de código. Cuando los nombres están bien elegidos, otros desarrolladores pueden entender rápidamente qué está haciendo la variable o función, y cómo está relacionada con el resto del código.</p><p>Aquí hay dos ejemplos en JavaScript que demuestran la importancia de tener nombres claros y descriptivos:</p><pre><code class="language-javascript">// Ejemplo 1: Denominación pobre
function ab(a, b) {
  let x = 10;
  let y = a + b + x;
  console.log(y);
}

ab(5, 3);</code></pre><p>En este ejemplo tenemos una función que toma dos parámetros, los suma a un valor predefinido de 10, y muestra por consola el resultado. El nombre de la función y nombres de variables están mal elegidos y no dan ninguna indicación de lo que la función hace o lo que las variables representan.</p><pre><code class="language-javascript">// Ejemplo 1: Buena denominación
function calcularTotalConImpuesto(precioBase, tasaImpuesto) {
  const IMPUESTO_BASE = 10;
  const totalConImpuesto = precioBase + (precioBase * (tasaImpuesto / 100)) + IMPUESTO_BASE;
  console.log(totalConImpuesto);
}

calcularTotalConImpuesto(50, 20);</code></pre><p>En este ejemplo tenemos una función que calcula el precio total de un producto incluyendo el impuesto. El nombre de la función y nombres de variables están bien elegidos y dan una clara indicación de lo que la función hace y lo que las variables representan.</p><p>Esto hace que el código sea más fácil de leer y entender, especialmente para otros desarrolladores que pueden estar trabajando con la base de código en el futuro.</p><!--kg-card-begin: html--><h2 id="claridad">Concisión vs Claridad</h2><!--kg-card-end: html--><p>Al momento de escribir código limpio es importante encontrar un balance entre concisión y claridad. Si bien es importante mantener el código conciso para mejorar la legibilidad y mantenibilidad, es igual de importante asegurar que el código sea claro y fácil de entender. Escribir código demasiado conciso puede llegar a confusión y errores, y puede hacer que el código sea difícil de trabajar para otros desarrolladores.</p><p>Aquí hay dos ejemplos que demuestran la importancia de concisión y claridad:</p><pre><code class="language-javascript">// Ejemplo 1: Función concisa
const cuentaVocales = s =&gt; (s.match(/[aeiou]/gi) || []).length;
console.log(cuentaVocales("hola mundo"));</code></pre><p>Este ejemplo usa la función flecha concisa y expresiones regulares para contar el número de vocales en una cadena de caracteres dada. Si bien el código es bastante corto y fácil de escribir, puede que no sea inmediatamente claro para otro desarrollador saber cómo funciona el patrón de expresión regular, especialmente si no están familiarizados con la sintaxis de expresiones regulares.</p><pre><code class="language-javascript">// Ejemplo 2: Función más detallada y más clara
function contarVocales(s) {
  const vocalRegex = /[aeiou]/gi;
  const coincidencias = s.match(vowelRegex) || [];
  return coincidencias.length;
}

console.log(contarVocales("hola mundo"));
</code></pre><p>Este ejemplo usa una función tradicional y expresión regular para contar el número de vocales en una cadena dada, pero lo hace de una forma que es clara y fácil de entender. El nombre de la función y los nombres de variables son descriptivos, y al patrón de expresión regular se almacena con un nombre claro. Esto hace que se vea fácilmente lo que está haciendo la función y cómo funciona.</p><p>Es importante encontrar un balance entre concisión y claridad al escribir código. Si bien el código conciso puede mejorar la legibilidad y mantenibilidad, es importante asegurar que el código siga estándo claro y fácil de entender para otros desarrolladores que puedan trabjar en la base de código en el futuro.</p><p>Al usar nombres de funciones y variables descriptivos, y hacer uso de formateo de código claro y legible, y comentarios, es posible escribir código limpio y conciso que sea fácil de entender y trabajar con él.</p><!--kg-card-begin: html--><h2 id="reusabilidad">Reusabilidad</h2><!--kg-card-end: html--><p>La reusabilidad del código es un concepto fundamental en la ingeniería de software que hace referencia a la capacidad del código a user usado varias veces sin modificación.</p><p>La importancia de la reusabilidad del código se encuentra en el hecho que puede mejorar en gran medida la eficiencia y productividad del desarrollo del software al reducir la cantidad de código que necesita ser escrito y testeado.</p><p>Al reutilizar código existente, los desarrolladores pueden ahorra tiempo y esfuerzo, mejorar la calidad &nbsp;y coherencia del código, minimizando el riesgo de introducir bugs y errores. El código reutilizable también permite arquitecturas de software más modulares y escalables, haciendo que sea más fácil mantener y actualizar la base de código con el tiempo.</p><pre><code class="language-javascript">// Ejemplo 1: Sin reusabilidad
function calcularAreaCirculo(radio) {
  const PI = 3.14;
  return PI * radio * radio;
}

function calcularAreaRectangulo(largo, ancho) {
  return largo * ancho;
}

function calcularAreaTriangulo(base, alto) {
  return (base * alto) / 2;
}

const areaCirculo = calcularAreaCirculo(5);
const areaRectangulo = calcularAreaRectangulo(4, 6);
const areaTriangulo = calcularAreaTriangulo(3, 7);

console.log(areaCirculo, areaRectangulo, areaTriangulo);</code></pre><p>Este ejemplo define tres funciones que calculan el área de un círculo, rectángulo y triángulo, respectivamente. Cada función realiza una tarea específica, pero ninguna de ellas es re-utilizable para otras tareas similares.</p><p>Además, el uso de un valor PI predefinido puede llevar a errores si en el futuro el valor necesita cambiarse. El código es ineficiente debido a que repite varias veces la misma lógica.</p><pre><code class="language-javascript">// Ejemplo 2: Implementando reusabilidad
function calcularArea(forma, ...args) {
  if (forma === 'circulo') {
    const [radio] = args;
    const PI = 3.14;
    return PI * radio * radio;
  } else if (forma === 'rectangulo') {
    const [larho, ancho] = args;
    return larho * ancho;
  } else if (forma === 'triangulo') {
    const [base, altura] = args;
    return (base * altura) / 2;
  } else {
    throw new Error(`Forma "${forma}" no soportada.`);
  }
}

const areaCirculo = calcularArea('circulo', 5);
const areaRectangulo = calcularArea('rectangulo', 4, 6);
const areaTriangulo = calcularArea('triangulo', 3, 7);

console.log(areaCirculo, areaRectangulo, areaTriangulo);
</code></pre><p>Este ejemplo define una sola función <code>calcularArea</code> que toma el argumento <code>forma</code> y una cantidad variable de argumentos. En base al argumento <code>forma</code> la función realiza el cálculo apropiado y devuelve el resultado.</p><p>Este enfoque es mucho más eficiente ya que eliminamos la necesidad de repetir código para tareas similares. También es más flexible y extensible ya que se puede agregar fácilmente formas adicionales en el futuro.</p><!--kg-card-begin: html--><h2 id="flujo">Flujo Claro de Ejecución</h2><!--kg-card-end: html--><p>Tener un flujo claro de ejecución es fundamental para escribir código limpio debido a que esto hace que el código sea más fácil de leer, entender y mantener. &nbsp;El código que siga una estructura clara y lógica es menos propensa a errores, fácil de modificar y extender, y más eficiente en términos de tiempo y recursos.</p><p>Por otro lado, el código espagueti es un término usado para describir código que es complejo y difícil de seguir, a menudo caracterizado por bloques de código largos, enredado y desorganizado. El código espagueti puede ser el resultado de malas decisiones de diseño, acoplamiento excesivo, o falta de documentación y comentarios adecuados.</p><p>Aquí hay dos ejemplos de código JavaScript que realiza la misma tarea, una con un flujo de ejecución claro, y el otro con código espagueti:</p><pre><code class="language-javascript">// Ejemplo 1: Flujo claro de ejecución
function calcularDescuento(precio, porcentajeDescuento) {
  const montoDescuento = precio * (porcentajeDescuento / 100);
  const precioDescontado = precio - montoDescuento;
  return precioDescontado;
}

const precioOriginal = 100;
const porcentajeDescuento = 20;
const precioFinal = calcularDescuento(precioOriginal, porcentajeDescuento);

console.log(precioFinal);

// Ejemplo 2: Código espagueti
const precioOriginal = 100;
const porcentajeDescuento = 20;

let precioDescontado;
let montoDescuento;
if (precioOriginal &amp;&amp; porcentajeDescuento) {
  montoDescuento = precioOriginal * (porcentajeDescuento / 100);
  precioDescontado = precioOriginal - montoDescuento;
}

if (precioDescontado) {
  console.log(precioDescontado);
}
</code></pre><p>Como podemos ver, el ejemplo 1 sigue una estructura clara y lógica, con una función que toma los parámetros necesarios y devuelve al resultado calculado. Por otra parte, el ejemplo 2 es mucho más complejo, con variables declaradas fuera de cualquier función y varias sentencias if usadas para verificar si el bloque de código se ha ejecutado con éxito.</p><!--kg-card-begin: html--><h2 id="principio">Principio de Responsabilidad Única</h2><!--kg-card-end: html--><p>El Principio de Responsabilidad Única (PRU) es un principio en el desarrollo de software que dice que cada clase o módulo debe tener sólo una razón para cambiar, o en otras palabras, cada entidad en nuestra base de código debe tener una única responsabilidad.</p><p>Este principio nos ayuda a crear código que es fácil de entender, mantener y extender.</p><p>Al aplicar PRU podemos crear código que es más fácil de testear, reusar y refactorizar, ya que cada módulo sólo maneja una única responsabilidad. Esto hace que sea menos probable que tenga efectos secundarios o dependencias que puedan dificultar el trabajo con el código.</p><pre><code class="language-javascript">// Ejemplo 1: Sin PRU
function procesarPedido(pedido) {
  // validar pedido
  if (pedido.items.length === 0) {
    console.log("Error: El Pedido no tiene elementos");
    return;
  }
  
  // calcular el total
  let total = 0;
  pedido.items.forEach(item =&gt; {
    total += item.precio * item.cantidad;
  });
  
  // aplicar descuentos
  if (pedido.cliente === "vip") {
    total *= 0.9;
  }
  
  // guardar pedido
  const db = new Database();
  db.connect();
  db.guardarPedido(pedido, total);
}
</code></pre><p>En este ejemplo, la función <code>procesarPedido</code> maneja varias responsabilidades: valida el pedido, calcula el total, aplica descuentos y guarda la órden en la base de datos. Esto hace que la función sea larga y difícil de entender, y cualquier cambio a una responsabilidad puede afectar a las otras, haciéndolo difícil de mantener.</p><pre><code class="language-javascript">// Ejemplo 2: Con PRU
class ProcesadorDePedidos {
  constructor(pedido) {
    this.pedido = pedido;
  }
  
  validar() {
    if (this.pedido.items.length === 0) {
      console.log("Error: El Pedido no tiene elementos");
      return false;
    }
    return true;
  }
  
  calcularTotal() {
    let total = 0;
    this.pedido.items.forEach(item =&gt; {
      total += item.precio * item.cantidad;
    });
    return total;
  }
  
  aplicarDescuentos(total) {
    if (this.pedido.cliente === "vip") {
      total *= 0.9;
    }
    return total;
  }
}

class GuardarPedido {
  constructor(pedido, total) {
    this.pedido = pedido;
    this.total = total;
  }
  
  guardar() {
    const db = new Database();
    db.connect();
    db.guardarPedido(this.pedido, this.total);
  }
}

const pedido = new Pedido();
const procesador = new ProcesadorDePedidos(order);

if (procesador.validar()) {
  const total = procesador.calcularTotal();
  const totalConDescuentos = procesador.aplicarDescuentos(total);
  const saver = new GuardarPedido(pedido, totalConDescuentos);
  saver.save();
}
</code></pre><p>En este ejemplo la función <code>procesarPedido</code> ha sido dividida en dos clases que siguen el PRU: <code>ProcesadorDePedidos</code> y <code>GuardarPedido</code>.</p><p>La clase <code>ProcesadorDePedidos</code> maneja las responsabilidades de validar el pedido, calcular el total y aplicar descuentos, mientras que la clase <code>GuardarPedido</code> maneja la responsabilidad de guardar el pedido en la base de datos.</p><p>Esto hace que el código sea más fácil de entender, hacer pruebas y mantener, ya que cada clase tiene una clara responsabilidad y puede ser modificada o reemplazada sin afectar a las demás.</p><!--kg-card-begin: html--><h2 id="fuente">Tener una "Fuente Única de la Verdad"</h2><!--kg-card-end: html--><p>Tener una "fuente única de la verdad" significa que sólo existe un lugar donde se guarda un dato o configuración en particular &nbsp;en la base de código, y cualquier otra referencia a él en el código se refiere a esa fuente. Esto es importante por que nos asegura que la información es consistente y evita la duplicación y contradicciones.</p><p>Aquí hay un ejemplo para ilustrar el concepto. Digamos que tenemos una aplicación que necesita mostrar las condiciones climáticas actuales en una ciudad. Podríamos implementar ésta característica de dos maneras diferentes:</p><pre><code class="language-javascript">// Opción 1: Sin "fuente única de la verdad"

// archivo 1: weatherAPI.js
const apiKey = '12345abcde';

function obtenerClimaActual(ciudad) {
  return fetch(`https://api.weather.com/conditions/v1/${city}?apiKey=${apiKey}`)
    .then(response =&gt; response.json());
}

// archivo 2: weatherComponent.js
const apiKey = '12345abcde';

function mostrarClimaActual(ciudad) {
  obtenerClimaActual(ciudad)
    .then(informacionClima =&gt; {
      // mostrar informacionClima en la UI
    });
}</code></pre><p>En ésta opción, la clave API está duplicada en dos archivos distintos, esto hace difícil mantener y actualizar. Si alguna vez necesitamos cambiar la clave API, tenemos que recordar actualizarla en ambas partes.</p><pre><code class="language-javascript">// Opción 2: "Fuente Única de la Verdad"

// archivo 1: weatherAPI.js
const apiKey = '12345abcde';

function obtenerClimaActual(ciudad) {
  return fetch(`https://api.weather.com/conditions/v1/${city}?apiKey=${apiKey}`)
    .then(response =&gt; response.json());
}

export { obtenerClimaActual, apiKey };


// archivo 2: weatherComponent.js
import { obtenerClimaActual } from './weatherAPI';

function mostrarClimaActual(ciudad) {
  obtenerClimaActual(ciudad)
    .then(informacionClima =&gt; {
      // mostrar informacionClima en la UI
    });
}
</code></pre><p>En ésta opción se guarda la clave API en un lugar (en el archivo <code>weatherAPI.js</code> ) y exported para que la usen otros módulos. Esto asegura que solo exista una única fuente de la verdad para la clave API y evita la duplicación y contradicciones.</p><p>Si alguna vez necesitamos actualizar la clave API, lo podemos hacer en un lugar y todos los otros módulos que la utilizan automáticamente obtendrán el valor actualizado.</p><!--kg-card-begin: html--><h2 id="exponer">Expón y Consume los Datos que Necesitas</h2><!--kg-card-end: html--><p>Un principio importante de escribir código limpio es solo exponer y consumir la información que sea necesaria para una tarea en particular. Esto ayuda a reducir la complejidad, aumenta la eficiencia y evita errores que pueden surgir de usar información innecesaria.</p><p>Cuando se expone o consume información que no es necesaria, puede llegar a problemas de desempeño y hacer que el código sea más difícil de entender y mantener.</p><p>Supongamos que tenemos un objeto con varias propiedades, pero solo necesitas usar un par de ellas. Una manera de hacer esto sería haciendo referencia al objeto y las propiedades específicas cada vez que las necesitemos. Pero esto puede volverse verboso y propenso a errores, especialmente si el objeto está profundamente anidado. Una solución clara y más eficiente sería usar la desestructuración de objeto para exponer y consumir únicamente la información que necesitas.</p><pre><code class="language-javascript">// Objeto original
const usuario = {
  id: 1,
  nombre: 'Alice',
  email: 'alice@example.com',
  edad: 25,
  direccion: {
    calle: '123 Main St',
    ciudad: 'Anytown',
    estado: 'CA',
    zip: '12345'
  }
};

// Expón y consume las propiedades nombre y email
const { nombre, email } = usuario;

console.log(nombre); // 'Alice'
console.log(email); // 'alice@example.com'
</code></pre><!--kg-card-begin: html--><h2 id="modularizacion">Modularización</h2>
<!--kg-card-end: html--><p>La modularización es un concepto fundamental para escribir código limpio. Se refiere a la práctica de descomponer código largo y complejo en módulos o funciones pequeñas más manejables. Esto hace que el código sea fácil de entender, probar y mantener.</p><p>Utilizar la modularización nos otorga varios beneficios tales como:</p><ol><li>Re-usabilidad: Los módulos pueden ser reutilizados en distintas partes de la aplicación o en otras aplicaciones, ahorrando tiempo y esfuerzo en el desarrollo.</li><li>Encapsulado: Los módulo te permiten ocultar los detalles internos de una función u objeto, exponiendo únicamente la interface básica al mundo exterior. Esto ayuda a reducir acoplamiento entre las distintas partes del código y mejorar la calidad del código en general.</li><li>Escalabilidad: Al descomponer código largo en pequeñas partes modulares puedes fácilmente agregar o quitar funcionalidades sin afectar a toda la base de código.</li></ol><p>Aquí hay un ejemplo en JavaScript de un fragmento de código que realiza una tarea sencilla, uno sin usar modularización y el otro implementando la modularización.</p><pre><code class="language-javascript">// Sin modularización
function calcularPrecio(cantidad, precio, impuesto) {
  let subtotal = cantidad * precio;
  let total = subtotal + (subtotal * impuesto);
  return total;
}

// Sin modularización
let cantidad = parseInt(prompt("Ingresar cantidad: "));
let precio = parseFloat(prompt("Ingresar precio: "));
let impuesto = parseFloat(prompt("Ingresar impuesto: "));

let total = calcularPrecio(cantidad, precio, impuesto);
console.log("Total: $" + total.toFixed(2));
</code></pre><p>En el ejemplo de arriba la función <code>calcularPrecio</code> es usada para calcular el precio total de un elemento dado la cantidad, el precio y el impuesto. Sin embargo, esta función no está modularizada y está estrechamente acoplado con la lógica de ingreso y salida del usuario. Esto puede hacerlo difícil de probar y mantener.</p><p>Ahora veamos un ejemplo del mismo código usando la modularización:</p><pre><code class="language-javascript">// Con modularización
function calcularSubtotal(cantidad, precio) {
  return cantidad * precio;
}

function calcularTotal(subtotal, impuesto) {
  return subtotal + (subtotal * impuesto);
}

// Con modularización
let cantidad = parseInt(prompt("Ingresar cantidad: "));
let precio = parseFloat(prompt("Ingresar precio: "));
let impuesto = parseFloat(prompt("Ingresar impuesto: "));

let subtotal = calcularSubtotal(cantidad, precio);
let total = calcularTotal(subtotal, impuesto);
console.log("Total: $" + total.toFixed(2));
</code></pre><p>En el ejemplo de arriba la función <code>calcularPrecio</code> ha sido descompuesta en dos funciones más pequeñas: <code>calcularSubtotal</code> y <code>calcularTotal</code>. Estas funciones ahora están modularizadas y son responsables de calcular el subtotal y total respectivamente. Esto hace que el código sea más fácil de entender, testear y mantener, y también lo hace más reutilizable en otras partes de la aplicación.</p><p>La modularización también puede hacer referencia a la práctica de dividir un archivo de código en varios archivos más pequeños que mas adelante son compilados de vuelta a un único archico (o menos archivos). Ésta práctica tiene los mismos beneficios que ya hemos hablado.</p><!--kg-card-begin: html--><h2 id="carpetas">Estructura de Carpetas</h2><!--kg-card-end: html--><p>Elegir una buena estructura de carpetas es una parte fundamental de escribir código limpio. Una estructura de proyecto bien organizada ayuda a los desarrolladores encontrar y modificar código fácilmente, reduce la complejidad del código y mejora la escalabilidad y mantenibilidad del proyecto.</p><p>Por otra parte, una mala estructura de carpetas puede hacer que sea un desafío entender la arquitectura del proyecto, navegar por la base de código y puede llevar a confusión y errores.</p><p>Aquí hay ejemplos de una buena y una mala estructura de carpetas utilizando un proyecto de React como ejemplo:</p><pre><code class="language-javascript">// Mala estructura de carpetas
my-app/
├── App.js
├── index.js
├── components/
│   ├── Button.js
│   ├── Card.js
│   └── Navbar.js
├── containers/
│   ├── Home.js
│   ├── Login.js
│   └── Profile.js
├── pages/
│   ├── Home.js
│   ├── Login.js
│   └── Profile.js
└── utilities/
    ├── api.js
    └── helpers.js
</code></pre><p>En éste ejemplo, la estructura del proyecto está organizada alrededor de tipos de archivos, tal como componentes, contenedores y páginas.</p><p>Pero este enfoque puede llevar a confusión y duplicación ya que no está claro qué archivos pertenecen a dónde. Por ejemplo, el componente <code>Home</code> está presente en ambas carpetas <code>containers</code> y <code>pages</code>. También puede ser un desafío encontrar y modificar código, debido a que los desarrolladores pueden necesitar navegar varias carpetas para encontrar el código que necesitan.</p><pre><code class="language-javascript">// Buena estructura de carpetas
my-app/
├── src/
│   ├── components/
│   │   ├── Button/
│   │   │   ├── Button.js
│   │   │   ├── Button.module.css
│   │   │   └── index.js
│   │   ├── Card/
│   │   │   ├── Card.js
│   │   │   ├── Card.module.css
│   │   │   └── index.js
│   │   └── Navbar/
│   │       ├── Navbar.js
│   │       ├── Navbar.module.css
│   │       └── index.js
│   ├── pages/
│   │   ├── Home/
│   │   │   ├── Home.js
│   │   │   ├── Home.module.css
│   │   │   └── index.js
│   │   ├── Login/
│   │   │   ├── Login.js
│   │   │   ├── Login.module.css
│   │   │   └── index.js
│   │   └── Profile/
│   │       ├── Profile.js
│   │       ├── Profile.module.css
│   │       └── index.js
│   ├── utils/
│   │   ├── api.js
│   │   └── helpers.js
│   ├── App.js
│   └── index.js
└── public/
    ├── index.html
    └── favicon.ico
</code></pre><p>En este ejemplo la estructura del proyecto está organizada alrededor de características, tales como componentes, páginas y utilidades. Cada característica tiene su propia carpeta, la cual contiene todos los archivos relacionados con esa característica.</p><p>Este enfoque hace que sea más fácil encontrar y modificar código ya que todos los archivos relacionados a una característica están ubicados en la misma carpeta. También reduce la duplicación y complejidad del código debido a que las características están separadas y sus archivos relacionado están organizados juntos.</p><p>Por lo general, una buena estructura de carpetas debería estar organizada alrededor de características, no los tipos de archivos, y tiene que facilitar la búsqueda y modificación de código. Una clara y lógica estructura puede hacer que el proyecto sea más fácil de mantener, entender y escalar, mientras que una estructura confusa e inconsistente puede llevar a errores y confusión.</p><!--kg-card-begin: html--><h2 id="documentacion">Documentación</h2><!--kg-card-end: html--><p>La documentación es una parte fundamental de escribir código limpio. Una documentación adecuada no sólo ayuda a los desarrolladores que escribieron el código a entenderlo mejor en el futuro pero también hace que sea más fácil para otros desarrolladores leer y entender la base de código. Cuando el código está bien documentado puede ahorrar tiempo y esfuerzo en depurar y mantener el código. </p><p>Documentar es especialmente importante en casos donde las soluciones simples y fáciles de entender no pueden ser implementadas, casos donde la lógica de negocio es bastante compleja, y casos en donde la gente que no está familiarizada con la base de código tiene que interactuar con ella.</p><p>Una manera de documentar código es usando comentarios. Los comentarios pueden dar contexto y explicar lo que el código está haciendo. Pero es importante usar los comentarios &nbsp;sabiamente, solo comentar donde sea necesario y evitando los comentarios redundantes e innecesarios.</p><p>Otra forma de documentar código es usando documentación en línea. La documentación en línea está incorporada al código en sí y puede ser usada para explicar lo que hace una función or parte de código específica. La documentación en línea se usa a menudo en combinación con herramientas como JSDoc, que proporciona un estándar para documentar código en JavaScript.</p><p>Herramientas como Typescript también proporcionan documentación automática para tu base de código, lo cual es de mucha ayuda.</p><p>Por último, las herramientas como Swagger y Postman pueden ser usadas para documentar APIs, proporcionando una manera fácil de entender cómo interactuar con ellos.</p><p>Si te interesa saber cómo implementar, probar, consumir y documentar APIs, hace poco escribí dos guías para APIs REST y APIs GraphQL REST APIs and GraphQL APIs.</p><!--kg-card-begin: html--><h2 id="terminando">Terminando</h2><!--kg-card-end: html--><p>Bueno, como siempre, espero que hayan disfrutado el artículo y hayan aprendido algo nuevo.<br><br>Si quieres, también puedes seguirme en <a href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> o <a href="https://twitter.com/CoccaGerman">Twitter</a>. ¡Nos vemos en la próxima!</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2023/05/giphy.gif" class="kg-image" alt="giphy" width="600" height="400" loading="lazy"></figure> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo dar estilo a tus aplicaciones React con CSS como un profesional ]]>
                </title>
                <description>
                    <![CDATA[ React es una biblioteca de JavaScript para construir interfaces de usuario. Y ha ganado mucha popularidad en la comunidad del desarrollo front-end. Uno de los beneficios de usar React es su integración con CSS, lo que permite a los desarrolladores aplicar estilos a sus componentes de una manera modular y ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-dar-estilo-a-tus-aplicaciones-react-con-css-como-un-profesional/</link>
                <guid isPermaLink="false">641b726755e3ad15a8936b28</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Tue, 04 Apr 2023 01:36:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/03/pexels-tyler-hendy-52062.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/style-react-apps-with-css/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Style Your React Apps with CSS Like a Pro</a>
      </p><p>React es una biblioteca de JavaScript para construir interfaces de usuario. Y ha ganado mucha popularidad en la comunidad del desarrollo front-end.</p><p>Uno de los beneficios de usar React es su integración con CSS, lo que permite a los desarrolladores aplicar estilos a sus componentes de una manera modular y reutilizable.</p><p>En este tutorial aprenderás cómo integrar React con CSS como un profesional al entender las distintas maneras que puedes aplicar estilos a tus componentes. También aprenderás algunas buenas prácticas para la organización y mantenimiento de tu código CSS.</p><p>Al finalizar este tutorial deberías poder darle estilo a tus componentes React con confianza y construir interfaces de usuarios visualmente atractivas.</p><h3 id="lo-que-vas-a-aprender">Lo que vas a aprender</h3><p>Aquí hay algunas cosas que aprenderás:</p><ul><li>Cómo usar módulos de CSS para aplicar estilos de ámbito a los componentes</li><li>Cómo usar bibliotecas CSS en JS tales como styled-components para dar estilo a tus componentes</li><li>Cómo aplicar estilos adaptables a tus componentes utilizando media<strong> </strong>queries (en español "consultas de medios") &nbsp;y otras técnicas de diseño adaptable</li><li>Cómo usar animaciones y transiciones CSS para agregar efectos visuales dinámicos a tus componentes</li><li>Buenas prácticas para la organización y mantenimiento de tu CSS cuando trabajas con una aplicación de React grande.</li></ul><h2 id="c-mo-integrar-react-con-css"><strong>Cómo integrar React con CSS</strong></h2><p>Existen varias maneras de integrar React con CSS. Aquí hay algunas aproximaciones que puedes encontrar útiles:</p><h3 id="usar-estilos-en-l-nea"><strong>Usar estilos en línea</strong></h3><p>Puedes usar el atributo <code>style</code> en tus componentes React para especificar estilos in línea. Esto puede ser conveniente si sólo necesitas aplicar pocos estilos a un único elemento.</p><pre><code class="language-jsx">import React from 'react';

function MiComponente() {
  return (
    &lt;div style={{color: 'red', fontSize: '32px'}}&gt;
      Este texto es rojo y 32px
    &lt;/div&gt;
  );
}</code></pre><p>Esto es un componente funcional en React que retorna un único elemento div con estilos en línea. El estilo en línea establece el color del texto a rojo y el tamaño de la fuente en 32px. Cuando este componente es renderizado en una aplicación React, mostrará un texto rojo con tamaño de fuente 32px <a href="https://codepen.io/gatwirival/pen/JjBbqme">como puedes ver en este CodePen</a>.</p><h3 id="usando-un-archivo-css"><strong>Usando un archivo CSS</strong></h3><p>Puedes crear un archivo CSS e importarlo a tus componentes React. Esto es útil si tienes un conjunto de estilos que quieres reutilizar a través de múltiples componentes.</p><pre><code class="language-css">/* mis-estilos.css */
.texto-rojo {
  color: red;
}

.texto-grande {
  font-size: 32px;
}</code></pre><p>Éste es un archivo CSS que contiene dos selectores de clase, <code>.texto-rojo</code> y <code>.texto-grande</code>, los cuales se pueden utilizar para aplicar los estilos correspondientes a los elementos. La clase <code>.texto-rojo</code> establece el color del texto a rojo y la clase <code>.texto- grande</code> establece el tamaño de fuente a 32px.</p><p>Para usar estas clases en JSX necesitas importar el archivo de hoja de estilo en el archivo del componente y luego agregar el className a los elementos JSX:</p><pre><code class="language-jsx">import React from 'react';
import './mis-estilos.css';

function MiComponente() {
  return (
    &lt;div className="texto-rojo texto-grande"&gt;
      Este texto es rojo y 32px
    &lt;/div&gt;
  );
}</code></pre><p><a href="https://codepen.io/gatwirival/pen/oNMePNQ">Echa un vistazo al código en Codepen</a>.</p><h3 id="usando-un-preprocesador-de-css"><strong>Usando un </strong>preprocesador de CSS</h3><p>Puedes usar un preprocesador de CSS (como SASS o LESS) para escribir y organizar tus estilos. Esto puede ser conveniente &nbsp;si quieres usar características como variables, mixins, y selectores anidados en tus estilos.</p><pre><code class="language-css">/* mis-estilos.scss */
$rojo: red;

.text-rojo {
  color: $red;
}

.texto-grande {
  font-size: 32px;
}</code></pre><p>Este es un archivo SCSS (Sass) que usa variables para guardar valores de colores, el cual puede ser reutilizado en toda la hoja de estilo. Se establece la variable <code>$rojo</code> al valor de <code>red</code>, y luego es usada para establecer el color del texto de la clase <code>.texto-rojo</code>. Además de esto, la clase <code>.texto-grande</code> establece el tamaño de fuente a 32px.</p><pre><code class="language-jsx">import React from 'react';
import './mis-estilos.scss';

function MiComponente() {
  return (
    &lt;div className="texto-rojo texto-grande"&gt;
      Este texto es rojo y 32px
    &lt;/div&gt;
  );
}</code></pre><p>Este es un componente funcional React que importa el archivo <code>mis-estilos.scss</code> y utiliza los selectores de clase definidos en ese archivo para dar estilo a los elementos en el JSX. La sentencia <code>import</code> en la parte superior del archivo es usada para importar el archivo <code>mis-estilos.scss</code> dentro del componente, permitiendo al componente usar las clases CSS definidas en ese archivo.</p><p>El JSX dentro de la función <code>MiComponente</code> retorna un único elemento <code>div</code> con el nombre de clase (className) <code>texto-rojo texto-grande</code>. Esto significa que el elemento div tendrá ambos estilos de clases <code>.texto-rojo</code> y <code>.texto-grande</code> que fueron definidas en el archivo <code>mis-estilos.scss</code>, dando como resultado el texto dentro del div que sea rojo y de tamaño 32px.</p><p>Cuando este componente es renderizado por la aplicación React, mostrará un texto rojo con tamaño de fuente 32px. Puedes ver el código funcionando <a href="https://codepen.io/gatwirival/pen/bGjrxBw">aquí</a>.</p><h3 id="usando-una-biblioteca-css-en-js"><strong>Usando una biblioteca </strong>CSS en JS</h3><p>También hay varias bibliotecas que te permiten componer tus estilos en JavaScript y aplicarlos a tus componentes.</p><p>Esto puede ser conveniente si quieres generar estilos de manera dinámica o aprovechar las características como tematización. Algunas bibliotecas populares de CSS en JS son styled-components y emotion.</p><pre><code class="language-jsx">import React from 'react';
import styled from 'styled-components';

const TextoRojo = styled.div`
  color: red;
  font-size: 32px;
`;

function MiComponente() {
  return (
    &lt;TextoRojo&gt;
      Este texto es rojo y 32px
    &lt;/TextoRojo&gt;
  );
}
</code></pre><p>Este es un componente funcional React que usar la biblioteca "styled-components" para dar estilo los elementos JSX. La biblioteca <code>styled-components</code> te permite escribir código CSS para darle estilo a tus componentes de una manera que tiene alcance a ese componente. También te permite usar expresiones JavaScript en tu CSS.</p><p>Aquí el componente importa el objeto <code>styled</code> desde la biblioteca <code>styled-components</code> y crea un nuevo componente llamado <code>TextoRojo</code> que renderiza un elemento <code>div</code> con los estilos definidos dentro de las comillas invertidas. Los estilos definidos dentro de las comillas invertidas establecen el color de text a rojo y el tamaño de fuente en 32px.</p><p>Luego el componente retorna JSX que usa el componente <code>TextoRojo</code>, el cual muestra un div con los estilos definidos.</p><p>Cuando este componente es renderizado por la aplicación React, se mostrará un texto rojo con tamaño de fuente 32px.</p><p>Éste método de dar estilo te permite crear componentes independientes reutilizables, con sus propios estilos que son fácil de manejar y probar.</p><h2 id="c-mo-usar-animaciones-y-transiciones-css-para-agregar-efectos-visuales-din-micos-a-tus-componentes"><strong>Cómo usar animaciones y transiciones CSS para agregar efectos visuales dinámicos a tus componentes</strong></h2><p>Para usar animaciones y transiciones CSS en un componente React vas a necesitar usar un objeto de estilo o una hoja de estilos externa para definir los estilos para tu componente.</p><p>Aquí hay un ejemplo de cómo usar una hoja de estilos para definir una animación CSS simple que desdibuja un elemento cuando es montado:</p><pre><code class="language-jsx">import React, { useEffect } from 'react';

function FadeInElement() {
  const [fadeIn, setFadeIn] = useState(false);

  useEffect(() =&gt; {
    setFadeIn(true);
  }, []);

  const fadeInStyle = {
    opacity: fadeIn ? 1 : 0,
    transition: 'opacity 500ms linear'
  };

  return &lt;div style={fadeInStyle}&gt;Fade In Element&lt;/div&gt;;
}
</code></pre><p>Este es un componente funcional React que usar los Hooks de React para crear una simple animación que "desdibuja" un elemento en la pantalla.</p><p>El componente usa el hook <code>useState</code> para manejar el estado del componente, en este caso es un valor booleano que determina si el elemento debe o no estar visible.</p><p>El componente también usa el hook <code>useEffect</code> para escuchar los cambios en el componente y establece el estado <code>fadeIn</code> a verdadero cuando el componente es renderizado. El useEffect toma un arreglo vacío como segundo argumento, esto significa que sólo va a ejecutarse una vez cuando el componente se renderiza por primera vez (en el montaje).</p><p>El componente luego define un objeto <code>fadeInStyle</code> que usa el estado <code>fadeIn</code> para establecer la opacidad del elemento. Si <code>fadeIn</code> es verdadero, el elemento será completamente opaco (opacidad: 1), de lo contrario será completamente transparente (opacidad: 0). La propiedad "transition" también se establece para hacer una transición suave a lo largo de 500ms.</p><p>El componente retorna un elemento <code>div</code> con el objeto <code>fadeInStyle</code> como su estilo en línea. Cuando este componente es renderizado por una aplicación React, mostrará el texto "Fade In Element" que se dibuja suavemente a lo largo de un periodo de 500ms. Puedes ver el código funcionando <a href="https://codepen.io/gatwirival/pen/KKBvxWq">aquí</a>. </p><p>También puedes usar la prop <code>className</code> y una hoja de estilos externa para definir tus estilos. Aquí hay un ejemplo que usa una hoja de estilos externa para definir una transición CSS simple que cambia el color de un elemento cuando se le pasa el mouse por encima:</p><pre><code class="language-jsx">import React from 'react';
import './FadeInElement.css';

function FadeInElement() {
  return &lt;div className="fade-in-element"&gt;Hover Me&lt;/div&gt;;
}</code></pre><pre><code class="language-css">.fade-in-element {
  transition: color 500ms linear;
}

.fade-in-element:hover {
  color: blue;
}
</code></pre><p>También puedes usar la regla <code>@keyframes</code> para determinar animaciones más complejas. Por ejemplo:</p><pre><code class="language-css">@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.pulse {
  animation: pulse 500ms linear;
}</code></pre><p>También puedes aplicar la animación <code>pulse</code> a un elemento usando la prop <code>className</code>:</p><pre><code class="language-jsx">import React from 'react';
import './PulseElement.css';

function PulseElement() {
  return &lt;div className="pulse"&gt;Pulse&lt;/div&gt;;
}</code></pre><h2 id="mejores-pr-cticas-para-la-organizaci-n-y-mantener-tu-css-en-una-aplicaci-n-react-grande"><strong>Mejores prácticas para la organización y mantener tu CSS en una </strong>aplicación React grande</h2><h3 id="usar-una-biblioteca-css-en-js"><strong>Usar una biblioteca CSS en JS</strong></h3><p>Bibliotecas CSS en JS como styled-components y emotion te permiten definir tus estilos en JavaScript y automáticamente colocarlos en el ámbito de tus componentes tal como se muestra arriba. Esto puede ayudar a prever conflictos de nombres y hacer que sea más fácil manejar tus estilos.</p><h3 id="usar-convenci-n-de-nomenclatura"><strong>Usar </strong>convención de nomenclatura</h3><p>Es una buena idea usar una convención de nomenclatura consistente para tus clases CSS para mantener tus estilos organizados y fácil de entender. Algunas convenciones de nomenclatura populares son BEM (Bloque-Elemento-Modificador) y SMACSS (Arquitectura Escalable y Modular para CSS).</p><p>Aquí hay un ejemplo de cómo éstas convenciones puede ser usadas juntas en un componente React:</p><pre><code class="language-jsx">import React from 'react';
import './ProfileInfo.css';

function ProfileInfo(props) {
  return (
    &lt;div className="profile-info"&gt;
      &lt;h2&gt;{props.name}&lt;/h2&gt;
      &lt;p&gt;{props.bio}&lt;/p&gt;
    &lt;/div&gt;
  );
}

export default ProfileInfo;
</code></pre><p>Y el correspondiente CSS:</p><pre><code class="language-css">.profile-info {
  background-color: #f5f5f5;
  padding: 20px;
}</code></pre><p>En este código se usan las siguientes convenciones de nomenclatura:</p><ul><li>El componente funcional React se llama "ProfileInfo", lo que sigue la convención de nomenclatura UpperCamelCase (caso de camellos superior) o PascalCase para nombrar componentes de React.</li><li>El archivo CSS importado se llama "ProfileInfo.css", lo que también sigue la convención UpperCamelCase y coincide con el nombre del componente.</li><li>La clase en la plantilla JSX se llama "profile-info", lo que sigue la convención minúscula y separado por guiones, también conocida como kebab-case, para nombrar clases CSS.</li></ul><p>Puedes <a href="https://www.freecodecamp.org/news/snake-case-vs-camel-case-vs-pascal-case-vs-kebab-case-whats-the-difference/">leer más sobre convenciones de nomenclatura aquí si lo deseas</a>.</p><h3 id="usar-una-herramienta-de-tipo-linter"><strong>Usar una herramienta de tipo linter</strong></h3><p>Una herramienta de tipo linter es una herramienta que verifica tu código para detectar errores de estilo y sintáxis. Existen linters disponibles para CSS que te pueden ayudar a mantener tus estilos consistente y libre de errores.</p><p>Existen varios linters disponibles para verificar tu código CSS, tales como CSSLint, Styleline y ESLint.</p><p>Para usar un linter en CSS primero necesitas instalarlo. Por ejemplo, para instalar CSSLint, puedes usar npm ejecutando el siguiente comando:</p><pre><code class="language-bash">npm list -g csslint</code></pre><p>Una vez que se instala la herramienta linter, puedes usarla para verificar tu código CSS ejecutando el linter y pasando el archivo o archivos que quieres verificar como argumentos.</p><p>Por ejemplo, para verificar un archivo llamado "estilos.css" usando CSSLint, vas a necesitar cambiar tu directorio a la carpeta con el archivo CSS y luego ejecutar el siguiente comando:</p><pre><code class="language-bash">csslint estilos.css</code></pre><p>Después de ejecutar el comando de arriba vas a ver lo siguiente de acuerdo a los errores en tu código:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2023/01/Screenshot-from-2023-01-18-21-14-00.png" class="kg-image" alt="Screenshot-from-2023-01-18-21-14-00" width="600" height="400" loading="lazy"></figure><p>También puedes configurar el linter para usar reglas y configuraciones específicas al crear un archivo de configuración. El formato del archivo de configuración depende de la herramienta linter que estés usando. Por ejemplo, CSSLint usa un archivo <code>.csslintrc</code>.</p><p>Una vez que ejecutas el linter, éste va a imprimir por pantalla cualquier problema o advertencia que encuentra en tu código CSS. Luego puedes revisar la salida en pantalla y corregir cualquier problema que fue encontrado.</p><p>Nota: Dependiendo de la herramienta linter que estés usando, el proceso puede variar. Pero el concepto básico es el mismo.</p><h3 id="dividir-tus-estilos-en-archivos-separados"><strong>Dividir tus estilos en archivos separados</strong></h3><p>A medida que tu proyecto crezca puede ser útil dividir tus estilos en archivos separados, como un archivo para estilos base, uno para estilos de maquetación, y una para estilos temáticos. Esto puede facilitar encontrar y mantener tus estilos.</p><h3 id="usar-control-de-versiones"><strong>Usar c</strong>ontrol de versiones</h3><p>Usando un sistema de control de versiones como Git para realizar un seguimiento de los cambios en tus archivos CSS puede facilitar la colaboración con otros miembros del equipo y también revertir cambios si algo sale mal.</p><h3 id="usar-un-preprocesador-css"><strong>Usar un preprocesador CSS</strong></h3><p>Un preprocesador CSS como SASS y LESS te pueden ayudar a escribir y mantener tus estilos más eficientemente tal como se muestra abajo. Ellos te permiten usar variables, funciones y otras características que no están disponibles en CSS común.</p><h2 id="conclusi-n"><strong>Conclusión</strong></h2><p>Integrar React con CSS puede ser una herramienta poderosa para construir aplicaciones web eficientes y elegantes.</p><p>Al entender los principios del framework React y cómo interactúa con CSS, vas a poder aprovechar las fortalezas de ambas tecnologías y crear interfaces de usuario dinámicas y expresivas.</p><p>Tanto si eres un desarrollador experimentado como si acabas de empezar con React, aprender a integrar CSS de forma eficaz puede llevar tus habilidades al siguiente nivel y ayudarte a crear aplicaciones realmente impresionantes.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Elementos semánticos HTML5 explicados ]]>
                </title>
                <description>
                    <![CDATA[ Los elementos semánticos HTML son aquellos que describen claramente su significado de una manera legible por humanos y máquinas. Elementos tales como <header>, <footer> y <article> son considerados semánticos porque describen con precisión el propósito del elemento y el tipo de contenido que hay dentro de ellos. ¿Qué son los ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/elementos-semanticos-html5-explicados/</link>
                <guid isPermaLink="false">63efb7a922450a0629adcb42</guid>
                
                    <category>
                        <![CDATA[ html5 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Mon, 06 Mar 2023 14:07:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/02/5f9c9ebe740569d1a4ca3ed0.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/semantic-html5-elements/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Semantic HTML5 Elements Explained</a>
      </p><p>Los elementos semánticos HTML son aquellos que describen claramente su significado de una manera legible por humanos y máquinas.</p><p>Elementos tales como <code>&lt;header&gt;</code>, <code>&lt;footer&gt;</code> y <code>&lt;article&gt;</code> son considerados semánticos porque describen con precisión el propósito del elemento y el tipo de contenido que hay dentro de ellos.</p><h3 id="-qu-son-los-elementos-sem-nticos"><strong>¿Qué son los Elementos Semánticos<strong><strong>?</strong></strong></strong></h3><p>HTML fue creado originalmente como lenguaje de código para describir documentos en los comienzos de internet. A medida que internet crecía y fue adoptado por más gente, sus necesidades cambiaron.</p><p>Donde internet estaba destinado para compartir documentos científicos, ahora la gente también quería compartir otras cosas. Muy rápidamente, la gente comenzó a querer que la web se viera mejor.</p><p>Debido a que la web no se creó inicialmente para ser diseñada, los programadores usaron diferentes trucos para hacer que las cosas estén dispuestas en diferentes maneras. En lugar de usar <code>&lt;table&gt;&lt;/table&gt;</code> para describir información usando una tabla, los programadores las usarían para posicionar otros elementos en una página.</p><p>A medida que avanzaba el uso de maquetaciones visualmente diseñadas, los programadores comenzaron a usar una etiqueta genérica "no semántica" como <code>&lt;div&gt;</code>. A menudo les darían a estos elementos un atributo <code>class</code> o <code>id</code> para describir su propósito. Por ejemplo, en lugar de <code>&lt;header&gt;</code> esto era a menudo escrito como <code>&lt;div class="header"&gt;</code>.</p><p>Como HTML5 es todavía relativamente nuevo, este uso de elementos no semánticos sigue siendo muy común en los sitios web de hoy.</p><h3 id="listado-de-nuevos-elementos-sem-nticos"><strong>Listado de nuevos elementos semánticos</strong></h3><p>Los elementos semánticos agregados a HTML5 son:</p><ul><li><code>&lt;article&gt;</code></li><li><code>&lt;aside&gt;</code></li><li><code>&lt;details&gt;</code></li><li><code>&lt;figcaption&gt;</code></li><li><code>&lt;figure&gt;</code></li><li><code>&lt;footer&gt;</code></li><li><code>&lt;header&gt;</code></li><li><code>&lt;main&gt;</code></li><li><code>&lt;mark&gt;</code></li><li><code>&lt;nav&gt;</code></li><li><code>&lt;section&gt;</code></li><li><code>&lt;summary&gt;</code></li><li><code>&lt;time&gt;</code></li></ul><p>Elementos tales como <code>&lt;header&gt;</code>, <code>&lt;nav&gt;</code>, <code>&lt;section&gt;</code>, <code>&lt;article&gt;</code>, <code>&lt;aside&gt;</code>, y <code>&lt;footer&gt;</code> actúan más o menos como elementos <code>&lt;div&gt;</code>. Ellos agrupan otros elementos en secciones de página. Sin embargo, donde una etiqueta <code>&lt;div&gt;</code> puede contener cualquier tipo de información, es fácil identificar qué tipo de información iría dentro de una región semántica <code>&lt;header&gt;</code>.</p><p><strong>Un ejemplo de diseño<strong><strong><strong> </strong></strong></strong>de elementos semánticos por <strong><strong><strong>w3schools</strong></strong></strong></strong></p><h2 id="-por-qu-usar-elementos-sem-nticos"><strong>¿Por qué usar elementos semánticos?</strong></h2><p>Para ver los beneficios de los elementos semánticos, aquí hay dos fragmentos de código HTML. Este primer bloque de código usa elementos semánticos:</p><pre><code class="language-html">&lt;header&gt;&lt;/header&gt;
&lt;section&gt;
	&lt;article&gt;
		&lt;figure&gt;
			&lt;img&gt;
			&lt;figcaption&gt;&lt;/figcaption&gt;
		&lt;/figure&gt;
	&lt;/article&gt;
&lt;/section&gt;
&lt;footer&gt;&lt;/footer&gt;</code></pre><p>Mientras que el segundo bloque de código usa elementos no semánticos:</p><pre><code class="language-text">&lt;div id="header"&gt;&lt;/div&gt;
&lt;div class="section"&gt;
	&lt;div class="article"&gt;
		&lt;div class="figure"&gt;
			&lt;img&gt;
			&lt;div class="figcaption"&gt;&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footer"&gt;&lt;/div&gt;</code></pre><p>Primero, es mucho más <strong>fácil de leer</strong>. Esto probablemente sea lo primero que vas a notar al mirar al primer bloque de código que usa elementos semánticos. Este es un pequeño ejemplo, pero como programador puedes estar leyendo cientos o miles de líneas de código. Cuanto más fácil sea de leer y entender ese código, más fácil será tu trabajo.</p><p>Tiene una <strong>mayor accesibilidad</strong>. No eres el único al que le resultan más fáciles de comprender los elementos semánticos. Los buscadores y tecnologías de asistencia (como lectores de pantalla para usuarios con discapacidad visual) también pueden entender mejor el contexto y contenido de tu sitio web, lo que significa una mejor experiencia para tus usuarios.</p><p>En general, los elementos semánticos también pueden conducir a <strong>código más coherente</strong>. Al crear un encabezado usando elementos no semánticos, diferentes programadores pueden escribir esto como <code>&lt;div class="header"&gt;</code>, <code>&lt;div id="header"&gt;</code>, <code>&lt;div class="head"&gt;</code>, o simplemente <code>&lt;div&gt;</code>. Hay muchas formas de crear un elemento de encabezado y todas dependen de las preferencias personales del programador. Al crear un elemento semántico estándar, lo hace más fácil para todos.</p><p>Desde octubre 2014, se actualizó HTML4 a HTML5, junto con algunos nuevos elementos "semánticos". Hasta el día de hoy, es posible que algunos de nosotros aún no sepamos por qué tantos elementos diferentes que no parecen mostrar cambios importantes.</p><p><strong><strong><strong><code>&lt;section&gt;</code> </strong></strong>y<strong><strong> <code>&lt;article&gt;</code></strong></strong></strong></p><p>“¿Cuál es la diferencia?”, te podrías preguntar. Ambos elementos son utilizados para seccionar un contenido, y sí, definitivamente se pueden usar de manera intercambiable. Depende de la situación. HTML4 ofrecía solo un tipo de elemento contenedor, que es <code>&lt;div&gt;</code>. Si bien todavía se usa en HTML5, HTML5 nos proporciona una forma de reemplazar <code>&lt;div&gt;</code> con <code>&lt;section&gt;</code> y <code>&lt;article&gt;</code>.</p><p>Los elementos <code>&lt;section&gt;</code> y <code>&lt;article&gt;</code> son conceptualmente similares e intercambiables. Para poder decidir cual debes usar, toma nota de lo siguiente:</p><ol><li>Un artículo está destinado a ser independientemente distribuible o reutilizable.</li><li>Una sección es una agrupación temática de contenido.</li></ol><pre><code class="language-html">&lt;section&gt;
  &lt;p&gt;Historias destacadas&lt;/p&gt;
  &lt;section&gt;
    &lt;p&gt;Noticias&lt;/p&gt;
    &lt;article&gt;Noticia 1&lt;/article&gt;
    &lt;article&gt;Noticia 2&lt;/article&gt;
    &lt;article&gt;Noticia 3&lt;/article&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;p&gt;Deportes&lt;/p&gt;
    &lt;article&gt;Noticia 1&lt;/article&gt;
    &lt;article&gt;Noticia 2&lt;/article&gt;
    &lt;article&gt;Noticia 3&lt;/article&gt;
  &lt;/section&gt;
&lt;/section&gt;</code></pre><h4 id="header-y-hgroup"><strong><strong><strong><code>&lt;header&gt;</code> </strong></strong>y<strong><strong> <code>&lt;hgroup&gt;</code></strong></strong></strong></h4><p>El elemento <code>&lt;header&gt;</code> se encuentra casi siempre en la parte superior de un documento, una sección, o un artículo, y contiene generalmente el encabezado principal y alguna navegación y herramientas de búsqueda.</p><pre><code class="language-html">&lt;header&gt;
  &lt;h1&gt;Empresa A&lt;/h1&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/inicio"&gt;Inicio&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/sobre-nosotros"&gt;Sobre Nosotros&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/contacta"&gt;Contacta con nosotros&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;form target="/buscar"&gt;
    &lt;input name="q" type="search" /&gt;
    &lt;input type="submit" /&gt;
  &lt;/form&gt;
&lt;/header&gt;</code></pre><p>El elemento <code>&lt;hgroup&gt;</code> debe ser usado donde quieras un encabezado principal con uno o más sub encabezados.</p><pre><code class="language-html">&lt;hgroup&gt;
  &lt;h1&gt;Encabezadpo1&lt;/h1&gt;
  &lt;h2&gt;Subencabezado 1&lt;/h2&gt;
  &lt;h2&gt;Subencabezado 2&lt;/h2&gt;
&lt;/hgroup&gt;</code></pre><p>RECUERDA que el elemento <code>&lt;header&gt;</code> puede contener cualquier contenido, pero el elemento <code>&lt;hgroup&gt;</code> solo puede contener otros encabezados, esto es <code>&lt;h1&gt;</code> hasta <code>&lt;h6&gt;</code> incluso <code>&lt;hgroup&gt;</code>.</p><h4 id="aside"><strong><strong><strong><code>&lt;aside&gt;</code></strong></strong></strong></h4><p>El elemento <code>&lt;aside&gt;</code> está diseñado para el contenido que no forma parte del flujo del texto en el que aparece, sin embargo, sigue relacionado de alguna manera. De esta forma quedaría este <code>&lt;aside&gt;</code> como barra lateral a tu contenido principal.</p><pre><code class="language-html">&lt;aside&gt;
  &lt;p&gt;Esta es una barra lateral, por ejemplo, una definición de terminología o un breve resumen de una figura histórica.&lt;/p&gt;
&lt;/aside&gt;</code></pre><p>Antes de HTML5, nuestros menús eran creados con <code>&lt;ul&gt;</code>’s y <code>&lt;li&gt;</code>’s. Ahora, junto a estos, podemos separar nuestros ítems de menú con un <code>&lt;nav&gt;</code>, para la navegación entre tus páginas. Puedes tener cualquier cantidad de elementos <code>&lt;nav&gt;</code> en la página, por ejemplo, es común tener una navegación global a lo largo de la parte superior (en el <code>&lt;header&gt;</code>) y navegación local en una barra lateral (en un elemento <code>&lt;aside&gt;</code>).</p><pre><code class="language-html">&lt;nav&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/inicio"&gt;Inicio&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/sobre-nosotros"&gt;Sobre Nosotros&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/contacta"&gt;Contacta con nosotros&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;</code></pre><h4 id="footer"><strong><strong><strong><code>&lt;footer&gt;</code></strong></strong></strong></h4><p>Si existe un <code>&lt;header&gt;</code> debe existir un <code>&lt;footer&gt;</code>. Un <code>&lt;footer&gt;</code> por lo general se encuentra en la parte inferior del documento, una sección, o un artículo. Tal como él, <code>&lt;header&gt;</code> el contenido es generalmente meta-información, como detalles del autor, información legal, y/o enlaces a información relacionada. También es válido incluir elementos <code>&lt;section&gt;</code> dentro del pie de página.</p><pre><code class="language-html">&lt;footer&gt;&amp;copy;Empresa A&lt;/footer&gt;</code></pre><h4 id="small"><strong><strong><strong><code>&lt;small&gt;</code></strong></strong></strong></h4><p>El elemento <code>&lt;small&gt;</code> a menudo aparece dentro de un elemento <code>&lt;footer&gt;</code> o <code>&lt;aside&gt;</code> el cual en general contendría información de derechos de autor o avisos legales y otra letra chica. Sin embargo, esto no pretende hacer el texto más pequeño. Simplemente, describe su contenido, no prescribe la presentación. </p><pre><code class="language-html">&lt;footer&gt;&lt;small&gt;&amp;copy;Empresa A&lt;/small&gt; Fecha&lt;/footer&gt;</code></pre><h4 id="time"><strong><strong><strong><code>&lt;time&gt;</code></strong></strong></strong></h4><p>El elemento <code>&lt;time&gt;</code> nos permite adjuntar una fecha ISO 8601 no ambigua a una versión legible por humanos de esa fecha.</p><pre><code class="language-html">&lt;time datetime="2017-10-31T11:21:00+02:00"&gt;Martes, 31 de Octubre 2017&lt;/time&gt;</code></pre><p>¿Por qué molestarse con <code>&lt;time&gt;</code>? Si bien los humanos pueden leer el tiempo que puede eliminar la ambigüedad a través del contexto de una manera normal, las computadoras pueden leer la fecha ISO 8601 y ver la fecha, hora y zona horaria.</p><h4 id="figure-y-figcaption"><strong><strong><strong><code>&lt;figure&gt;</code> </strong></strong>y<strong><strong> <code>&lt;figcaption&gt;</code></strong></strong></strong></h4><p><code>&lt;figure&gt;</code> es para envolver el contenido de su imagen a su alrededor, y <code>&lt;figcaption&gt;</code> es para subtitular tu imagen.</p><pre><code class="language-html">&lt;figure&gt;
  &lt;img src="https://en.wikipedia.org/wiki/File:Shadow_of_Mordor_cover_art.jpg" alt="Sombras de Mordor" /&gt;
  &lt;figcaption&gt;Portada de La Tierra Media: Sombras de Mordor&lt;/figcaption&gt;
&lt;/figure&gt;</code></pre><h3 id="m-s-informaci-n-sobre-los-nuevos-elementos-de-html5-">Más información sobre los nuevos elementos de HTML5<strong><strong><strong>:</strong></strong></strong></h3><ul><li><a href="https://www.w3schools.com/html/html5_semantic_elements.asp">w3schools</a> proporciona descripciones simples y claras de muchos de los elementos de las noticias y cómo/dónde deben usarse.</li><li><a href="https://developer.mozilla.org/es/docs/Web/HTML/Element">MDN</a> también proporciona una gran referencia para todos los elementos HTML y profundiza en cada uno.</li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial de una aplicación React ABM: Cómo construir una aplicación de gestión de libros en React desde cero ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por Yogesh Chavan [https://www.freecodecamp.org/news/author/yogesh/] Artículo original React CRUD App Tutorial – How to Build a Book Management App in React from Scratch [https://www.freecodecamp.org/news/react-crud-app-how-to-create-a-book-management-app-from-scratch/] Traducido y adaptado por Ezequiel Castellanos [/espanol/news/author/ezequiel_caste/] En este artículo, construirás una aplicación de administración de libros en React desde cero. **Nota: ABM es ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/tutorial-de-una-aplicacion-react-abm-como-construir-una-aplicacion-de-gestion-de-libros-en-react-desde-cero/</link>
                <guid isPermaLink="false">60fb58e1dc46df0914bac63d</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Thu, 23 Sep 2021 12:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/08/book_management.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong>Artículo original escrito por </strong></strong><a href="https://www.freecodecamp.org/news/author/yogesh/">Yogesh Chavan</a><br><strong><strong>Artículo original </strong></strong><a href="https://www.freecodecamp.org/news/react-crud-app-how-to-create-a-book-management-app-from-scratch/">React CRUD App Tutorial – How to Build a Book Management App in React from Scratch</a><br><strong><strong>Traducido y adaptado por </strong></strong><a href="https://www.freecodecamp.org/espanol/news/author/ezequiel_caste/">Ezequiel Castellanos</a></p><p>En este artículo, construirás una aplicación de administración de libros en React desde cero.</p><p><em>**Nota: ABM es un acrónimo que se refiere a las cuatro funciones que se consideran necesarias para &nbsp;implentar una aplicacion de almacenamiento persistente: Agregar, Borrar y Modificar. ABM es equiválete lo que es conocido como CRUD en ingles, lo cual es: Create, Read, Update y Delete.</em></p><p>Al crear esta applicación, aprendaras:</p><ol><li>Como realizar operaciones ABM</li><li>Como usar React Router para la navegacion entre rutas</li><li>Como usar la API de contexto de React para pasar datos a traves de rutas</li><li>Como crear un Hook personalizado en React</li><li>Como almacenar datos en almacenamiento local para persistirlos incluso despues de actualizar la pagina.</li><li>Como administrar los datos almacenados en el almacenamiento local mediate un hook personalizado</li></ol><p>y mucho mas.</p><p>Usaremos React Hooks para construir esta aplicación. Así que si eres nuevo en React Hooks, echa un vistazo a mi artículo de <a href="https://levelup.gitconnected.com/an-introduction-to-react-hooks-50281fd961fe">introdución a React Hooks</a> para aprender los conceptos básicos.</p><blockquote>¿Quieres aprender Redux desde el principio absoluto y construir una aplicación de pedidos de alimentos desde cero? Echa un vistazo al curso de <a href="https://master-redux.yogeshchavan.dev/">Masterización Redux</a></blockquote><h2 id="configuraci-n-inicial"><strong>Configuración Inicial</strong></h2><p>Crea un nuevo proyecto usando <code>create-react-app</code>:</p><pre><code class="language-js">npx create-react-app book-management-app
</code></pre><p>Una vez creado el proyecto, elimina todos los archivos de la carpeta <code>src</code> y crea el <code>index.js</code> y <code>styles.scss</code> dentro de la carpeta <code>src</code>. Además, crea <code>components</code>, &nbsp;<code>context</code>, <code>hooks</code> y carpetas de <code>router</code> dentro de la carpeta <code>src</code>.</p><p>Instalar las dependencias necesarias:</p><pre><code class="language-js">yarn add bootstrap@4.6.0 lodash@4.17.21 react-bootstrap@1.5.2 node-sass@4.14.1 react-router-dom@5.2.0 uuid@8.3.2
</code></pre><p>Abre <code>styles.scss</code> y añade los estilos que tiene <a href="https://github.com/myogeshchavan97/react-book-management-app/blob/master/src/styles.scss">aquí</a>.</p><h2 id="como-crear-las-p-ginas-de-inicio"><strong>Como crear las </strong>páginas<strong> de inicio</strong></h2><p>Crea un nuevo archivo <code>Header.js</code> dentro de la carpeta <code>components</code> con el siguiente contenido:</p><pre><code class="language-jsx">import React from 'react';
import { NavLink } from 'react-router-dom';

const Header = () =&gt; {
  return (
    &lt;header&gt;
      &lt;h1&gt;Aplicación de Gestión de Libros&lt;/h1&gt;
      &lt;hr /&gt;
      &lt;div className="links"&gt;
        &lt;NavLink to="/" className="link" activeClassName="active" exact&gt;
          Lista de Libros
        &lt;/NavLink&gt;
        &lt;NavLink to="/add" className="link" activeClassName="active"&gt;
          Añade Libro
        &lt;/NavLink&gt;
      &lt;/div&gt;
    &lt;/header&gt;
  );
};

export default Header;
</code></pre><p>Aquí, hemos agregado dos enlaces de navegación usando el componente <code>NavLink</code> de <code>react-router-dom</code>: uno para ver una lista de todos los libros, y el otro para agregar un nuevo libro.</p><p>Estamos usando <code>NavLink</code> en lugar de la etiqueta de anclaje ( <code>&lt;a /&gt;</code>) para que la página no se actualice cuando un usuario haga clic en cualquiera de los enlaces.</p><p>Crea un nuevo llamado <code>BooksList.js</code> dentro de la carpeta <code>components</code> con el siguiente contenido:</p><pre><code class="language-js">import React from 'react';

const BooksList = () =&gt; {
  return &lt;h2&gt;Lista de libros&lt;/h2&gt;;
};

export default BooksList;
</code></pre><p>Crea un nuevo archivo llamado <code>AddBook.js</code> dentro de la carpeta <code>components</code> con el siguiente contenido:</p><pre><code class="language-jsx">import React from 'react';
import BookForm from './BookForm';

const AddBook = () =&gt; {
  const handleOnSubmit = (book) =&gt; {
    console.log(book);
  };

  return (
    &lt;React.Fragment&gt;
      &lt;BookForm handleOnSubmit={handleOnSubmit} /&gt;
    &lt;/React.Fragment&gt;
  );
};

export default AddBook;
</code></pre><p>En este archivo, estamos mostrando un componente <code>BookForm</code> (que aún no hemos creado).</p><p>Para el componente <code>BookForm</code> estamos pasando el método<code>handleOnSubmit</code> para que podamos hacer algún procesamiento más tarde una vez que enviemos el formulario.</p><p>Ahora, crea un nuevo archivo <code>BookForm.js</code> dentro de la carpeta <code>components</code> con el siguiente contenido:</p><pre><code class="language-jsx">import React, { useState } from 'react';
import { Form, Button } from 'react-bootstrap';
import { v4 as uuidv4 } from 'uuid';

const BookForm = (props) =&gt; {
  const [book, setBook] = useState({
    bookname: props.book ? props.book.bookname : '',
    author: props.book ? props.book.author : '',
    quantity: props.book ? props.book.quantity : '',
    price: props.book ? props.book.price : '',
    date: props.book ? props.book.date : ''
  });

  const [errorMsg, setErrorMsg] = useState('');
  const { bookname, author, price, quantity } = book;

  const handleOnSubmit = (event) =&gt; {
    event.preventDefault();
    const values = [bookname, author, price, quantity];
    let errorMsg = '';

    const allFieldsFilled = values.every((field) =&gt; {
      const value = `${field}`.trim();
      return value !== '' &amp;&amp; value !== '0';
    });

    if (allFieldsFilled) {
      const book = {
        id: uuidv4(),
        bookname,
        author,
        price,
        quantity,
        date: new Date()
      };
      props.handleOnSubmit(book);
    } else {
      errorMsg = 'Please fill out all the fields.';
    }
    setErrorMsg(errorMsg);
  };

  const handleInputChange = (event) =&gt; {
    const { name, value } = event.target;
    switch (name) {
      case 'quantity':
        if (value === '' || parseInt(value) === +value) {
          setBook((prevState) =&gt; ({
            ...prevState,
            [name]: value
          }));
        }
        break;
      case 'price':
        if (value === '' || value.match(/^\d{1,}(\.\d{0,2})?$/)) {
          setBook((prevState) =&gt; ({
            ...prevState,
            [name]: value
          }));
        }
        break;
      default:
        setBook((prevState) =&gt; ({
          ...prevState,
          [name]: value
        }));
    }
  };

  return (
    &lt;div className="main-form"&gt;
      {errorMsg &amp;&amp; &lt;p className="errorMsg"&gt;{errorMsg}&lt;/p&gt;}
      &lt;Form onSubmit={handleOnSubmit}&gt;
        &lt;Form.Group controlId="name"&gt;
          &lt;Form.Label&gt;Book Name&lt;/Form.Label&gt;
          &lt;Form.Control
            className="input-control"
            type="text"
            name="bookname"
            value={bookname}
            placeholder="Introduzce el nombre del libro"
            onChange={handleInputChange}
          /&gt;
        &lt;/Form.Group&gt;
        &lt;Form.Group controlId="author"&gt;
          &lt;Form.Label&gt;Book Author&lt;/Form.Label&gt;
          &lt;Form.Control
            className="input-control"
            type="text"
            name="author"
            value={author}
            placeholder="Introduzce el nombre del autor"
            onChange={handleInputChange}
          /&gt;
        &lt;/Form.Group&gt;
        &lt;Form.Group controlId="quantity"&gt;
          &lt;Form.Label&gt;Quantity&lt;/Form.Label&gt;
          &lt;Form.Control
            className="input-control"
            type="number"
            name="quantity"
            value={quantity}
            placeholder="Introduzce la cantidad disponible"
            onChange={handleInputChange}
          /&gt;
        &lt;/Form.Group&gt;
        &lt;Form.Group controlId="price"&gt;
          &lt;Form.Label&gt;Book Price&lt;/Form.Label&gt;
          &lt;Form.Control
            className="input-control"
            type="text"
            name="price"
            value={price}
            placeholder="Introduzce el precio del libro"
            onChange={handleInputChange}
          /&gt;
        &lt;/Form.Group&gt;
        &lt;Button variant="primary" type="submit" className="submit-btn"&gt;
          Someter
        &lt;/Button&gt;
      &lt;/Form&gt;
    &lt;/div&gt;
  );
};

export default BookForm;
</code></pre><p>Vamos a entender lo que estamos haciendo aquí.</p><p>Inicialmente, hemos definido un estado como un objeto usando el hook <code>useState</code> para almacenar todos los detalles introducidos de esta manera:</p><pre><code class="language-js">const [book, setBook] = useState({
    bookname: props.book ? props.book.bookname : '',
    author: props.book ? props.book.author : '',
    quantity: props.book ? props.book.quantity : '',
    price: props.book ? props.book.price : '',
    date: props.book ? props.book.date : ''
  });
</code></pre><p>Como utilizaremos el mismo componente <code>BookForm</code> para agregar y editar el libro, primero comprobemos si la prop de <code>book</code> pasa o no usando el operador ternario.</p><p>Si pasa la prop, la establecemos al valor pasado, de lo contrario una cadena vacía (<code>''</code>).</p><blockquote>No te preocupes si parece complicado ahora. Lo entenderás mejor una vez que construyamos alguna funcionalidad inicial.</blockquote><p>Luego agregamos un estado para mostrar un mensaje de error y usamos la sintaxis de desestructuración ES6 para referir cada una de las propiedades dentro del estado de esta manera:</p><pre><code class="language-js">const [errorMsg, setErrorMsg] = useState('');
const { bookname, author, price, quantity } = book;
</code></pre><p>Desde el componente <code>BookForm</code> estamos devolviendo un formulario donde ingresamos el nombre del libro, el autor del libro, la cantidad y el precio. Estamos usando el framework <a href="https://react-bootstrap.github.io/">react-bootstrap</a> para mostrar el formulario en un buen formato.</p><p>Cada campo de entrada ha añadido un controlador <code>onChange</code> que llama al método <code>handleInputChange</code>.</p><p>Dentro del método <code>handleInputChange</code>, hemos agregado una instrucción "switch" para cambiar el valor del estado en función del campo de entrada que se cambia.</p><p>Cuando escribimos cualquier cosa en el campo de entrada de <code>quantity</code>, <code>event.target.name</code> será la <code>quantity</code> por lo que la primera caja del interruptor &nbsp;coincidirá. Dentro de ese caso interruptor, estamos comprobando para ver si el valor introducido es un entero sin un punto decimal.</p><p>Si es así, solo actualizamos el estado como se muestra a continuación:</p><pre><code class="language-js">if (value === '' || parseInt(value) === +value) {
  setBook((prevState) =&gt; ({
    ...prevState,
    [name]: value
  }));
}
</code></pre><p>Por lo tanto, el usuario no puede ingresar ningún valor decimal para el campo de entrada de <code>quantity</code>.</p><p>Para el "switch case" <code>price</code>, estamos comprobando un número decimal con solo dos dígitos después del punto decimal. Así que hemos añadido una comprobación de expresión regular que se parece a esto: <code>value.match(/^\d{1,}(\.\d{0,2})?$/)</code>.</p><p>Si el valor del precio "price" coincide con la expresión regular solo entonces actualizamos el estado.</p><p><strong>Nota: </strong>Para los dos casos de switch <code>quantity</code> y <code>price</code>, también estamos verificando valores vacíos como este: <code>value === ''</code>. &nbsp;Esto es para permitir el valor introducido si es necesario.</p><p>Si esa comprobación, el usuario no podrá eliminar el valor ingresado presionando <code>Ctrl + A + Delete</code>.</p><p>Para todos los demás campos de entrada, se ejecutara el caso switch predeterminado que actualizara el estado en función del valor introducido por el usuario.</p><p>A continuación, una vez que enviemos el formulario, se llamara al método <code>handleOnSubmit</code>.</p><p>Dentro de este método, primero verificamos si el usuario ha ingresado todos los detalles usando el método de arreglo <code>every</code>:</p><pre><code class="language-js">const allFieldsFilled = values.every((field) =&gt; {
  const value = `${field}`.trim();
  return value !== '' &amp;&amp; value !== '0';
});
</code></pre><p>El método de arreglo <code>every</code> es uno de los métodos de arreglos más útiles en JavaScript.</p><blockquote>Echa un vistazo a mi artículo aquí para aprender sobre los métodos de arreglos de JavaScript más útiles junto con su compatibilidad con el navegador.</blockquote><p>Si todos los valores están rellenados, entonces estamos creando un objeto con todos los valores rellenados. También estamos llamando al método <code>handleOnSubmit</code> pasando "book" como argumento, de lo contrario estamos configurando un mensaje de error.</p><p>El método <code>handleOnSubmit</code> se pasa como prop desde el componente <code>AddBook</code>.</p><pre><code class="language-js">if (allFieldsFilled) {
  const book = {
    id: uuidv4(),
    bookname,
    author,
    price,
    quantity,
    date: new Date()
  };
  props.handleOnSubmit(book);
} else {
  errorMsg = 'Please fill out all the fields.';
}
</code></pre><p>Ten en cuenta que para crear un ID único estamos llamando al método <code>uuidv4()</code> &nbsp;desde el paquete <a href="https://www.npmjs.com/package/uuid">uuid</a> npm.</p><p>Ahora, crea un nuevo archivo <code>AppRouter.js</code> dentro de la carpeta del <code>router</code> con el siguiente contenido:</p><pre><code class="language-jsx">import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Header from '../components/Header';
import AddBook from '../components/AddBook';
import BooksList from '../components/BooksList';

const AppRouter = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;div&gt;
        &lt;Header /&gt;
        &lt;div className="main-content"&gt;
          &lt;Switch&gt;
            &lt;Route component={BooksList} path="/" exact={true} /&gt;
            &lt;Route component={AddBook} path="/add" /&gt;
          &lt;/Switch&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/BrowserRouter&gt;
  );
};

export default AppRouter;
</code></pre><p>Aquí, hemos configurado el enrutamiento para varios componentes como<code>BooksList</code> y <code>AddBook</code> utilizando la biblioteca <code>react-router-dom</code>.</p><blockquote>Si eres nuevo en React Router, echa un vistazo a mi curso gratuito de <a href="https://yogeshchavan1.podia.com/react-router-introduction">introducción de React Router</a>.</blockquote><p>Ahora, abre el archivo <code>src/index.js</code> y agrega el siguiente contenido dentro de él:</p><pre><code class="language-js">import React from 'react';
import ReactDOM from 'react-dom';
import AppRouter from './router/AppRouter';
import 'bootstrap/dist/css/bootstrap.min.css';
import './styles.scss';

ReactDOM.render(&lt;AppRouter /&gt;, document.getElementById('root'));
</code></pre><p>Ahora, inicia la aplicación React ejecutando el siguiente comando desde el terminal:</p><pre><code class="language-js">yarn start
</code></pre><p>Veras la siguiente pantalla cuando accedas la aplicación en <a href="http://localhost:3000/">http://localhost:3000/</a>.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2021/04/initial_screen.gif" class="kg-image" alt="initial_screen" width="600" height="400" loading="lazy"></figure><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2021/04/add_book.gif" class="kg-image" alt="add_book" width="600" height="400" loading="lazy"></figure><p>Como puedes ver, podemos agregar correctamente el libro y mostrarlo en la consola.<br><br>Pero en lugar de iniciar sesión en la consola, vamos a agregarlo a un almacenamiento local.</p><h2 id="c-mo-crear-un-hook-personalizado-para-el-almacenamiento-local"><strong>Cómo crear un hook personalizado para el almacenamiento local</strong></h2><p>El almacenamiento local es increíble. Nos permite almacenar fácilmente datos de aplicaciones en el navegador y es una alternativa a las cookies para almacenar datos.</p><p>La ventaja de usar almacenamiento local es que los datos se guardaran permanentemente en la cache del navegador hasta que los eliminemos manualmente para que podamos acceder a ellos incluso después de actualizar la página. &nbsp;Como puede saber, los datos almacenados en el estado de React se perderán una vez que actualicemos la página.</p><p>Hay muchos casos de uso para el almacenamiento local, y uno de ellos es almacenar artículos del carrito de compras para que no se eliminen incluso si actualizamos la página.</p><p>Para agregar datos al almacenamiento local, utilizamos el método <code>setItem</code> al proporcionar una clave y un valor:</p><pre><code class="language-js">localStorage.setItem(key, value)
</code></pre><blockquote>Tanto la clave como el valor tienen que ser una cadena. Pero también &nbsp;podemos almacenar el objeto JSON usando el método <code>JSON.stringify</code>.</blockquote><p>Para obtener más información sobre el almacenamiento local y sus diversas aplicaciones en detalle, consulta <a href="https://javascript.plainenglish.io/everything-you-need-to-know-about-html5-local-storage-and-session-storage-479c63415c0a?source=friends_link&amp;sk=f429aa5008683a3b0359db43f976efb3">este artículo</a>.</p><p>Crear un nuevo archivo <code>useLocalStorage.js</code> dentro de la carpeta <code>hooks</code> con el siguiente contenido:</p><pre><code class="language-jsx">import { useState, useEffect } from 'react';

const useLocalStorage = (key, initialValue) =&gt; {
  const [value, setValue] = useState(() =&gt; {
    try {
      const localValue = window.localStorage.getItem(key);
      return localValue ? JSON.parse(localValue) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  useEffect(() =&gt; {
    window.localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
};

export default useLocalStorage;
</code></pre><p>Aquí, hemos utilizado un hook <code>useLocalStorage</code> que acepta una <code>key</code> y <code>initialValue</code>.</p><p>Para declarar estado usando el hook <code>useState</code>, estamos usando inicialización perezosa (<a href="https://reactjs.org/docs/hooks-reference.html#lazy-initial-state">lazy initialization</a>).</p><p>Por lo tanto, el código dentro de la función pasada a <code>useState</code> se ejecutará solo una vez, incluso si el hook <code>useLocalStorage</code> se llama varias veces en cada re-renderización de la aplicación.</p><p>Así que inicialmente estamos comprobando para ver si hay algún valor en el almacenamiento local con la <code>key</code> proporcionada y devolver el valor mediante el análisis utilizando el <code>JSON.parse</code>:</p><pre><code class="language-js">try {
  const localValue = window.localStorage.getItem(key);
  return localValue ? JSON.parse(localValue) : initialValue;
} catch (error) {
  return initialValue;
}
</code></pre><p>Luego, si hay algún cambio en la <code>key</code> o en <code>value</code>, actualizaremos el almacenamiento local:</p><pre><code class="language-js">useEffect(() =&gt; {
    window.localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);

return [value, setValue];
</code></pre><p>Luego estamos devolviendo el <code>value</code> almacenado en el almacenamiento local y la función <code>setValue</code> que llamaremos para actualizar los datos de <code>localStorage</code>.</p><h2 id="c-mo-usar-el-hook-de-almacenamiento-local">Cómo usar el hook de almacenamiento local</h2><p>Ahora, vamos a usar este hook <code>useLocalStorage</code> para que podamos agregar o eliminar datos del almacenamiento local.</p><p>Abre el archivo <code>AppRouter.js</code> y utiliza el hook <code>useLocalStorage</code> dentro del componente:</p><pre><code class="language-js">import useLocalStorage from '../hooks/useLocalStorage';

const AppRouter = () =&gt; {
 const [books, setBooks] = useLocalStorage('books', []);
 
 return (
  ...
 )
}
</code></pre><p>Ahora, necesitamos pasar los <code>books</code> y <code>setBooks</code> como props al componente <code>AddBook</code> para que podamos agregar el libro al almacenamiento local.</p><p>Así que cambia la ruta desde este código:</p><pre><code class="language-jsx">&lt;Route component={AddBook} path="/add" /&gt;
</code></pre><p>al siguiente código:</p><pre><code class="language-jsx">&lt;Route
  render={(props) =&gt; (
    &lt;AddBook {...props} books={books} setBooks={setBooks} /&gt;
  )}
  path="/add"
/&gt;
</code></pre><p>Aquí, estamos usando el patrón props renderizado para pasar los props predeterminados que pasarón por React router junto con los <code>books</code> y <code>setBooks</code>.</p><blockquote>Echa un vistazo a mi curso gratuito de <a href="https://yogeshchavan1.podia.com/react-router-introduction">introducción de React Router</a> para comprender mejor este patrón de accesorios de renderizado y la importancia de usar la palabra clave de renderizado en lugar de <code>component</code>.</blockquote><p>Todo tu archivo <code>AppRouter.js</code> se verá así ahora:</p><pre><code class="language-jsx">import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Header from '../components/Header';
import AddBook from '../components/AddBook';
import BooksList from '../components/BooksList';
import useLocalStorage from '../hooks/useLocalStorage';

const AppRouter = () =&gt; {
  const [books, setBooks] = useLocalStorage('books', []);

  return (
    &lt;BrowserRouter&gt;
      &lt;div&gt;
        &lt;Header /&gt;
        &lt;div className="main-content"&gt;
          &lt;Switch&gt;
            &lt;Route component={BooksList} path="/" exact={true} /&gt;
            &lt;Route
              render={(props) =&gt; (
                &lt;AddBook {...props} books={books} setBooks={setBooks} /&gt;
              )}
              path="/add"
            /&gt;
          &lt;/Switch&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/BrowserRouter&gt;
  );
};

export default AppRouter;
</code></pre><p>Ahora abre <code>AddBook.js</code> y sustituir tu contenido por el siguiente código:</p><pre><code class="language-jsx">import React from 'react';
import BookForm from './BookForm';

const AddBook = ({ history, books, setBooks }) =&gt; {
  const handleOnSubmit = (book) =&gt; {
    setBooks([book, ...books]);
    history.push('/');
  };

  return (
    &lt;React.Fragment&gt;
      &lt;BookForm handleOnSubmit={handleOnSubmit} /&gt;
    &lt;/React.Fragment&gt;
  );
};

export default AddBook;
</code></pre><p>En primer lugar, estamos utilizando la sintaxis de desestructuración ES6 para acceder a la <code>history</code>, <code>books</code> y props <code>setBooks</code> en el componente.</p><p>El prop de <code>history</code> es pasado automáticamente por el React Router a cada componente mencionado en el <code>&lt;Route /&gt;</code>. Estamos pasando los props <code>books</code> y <code>setBooks</code> desde el archivo <code>AppRouter.js</code>.</p><p>Estamos almacenando todos los libros agregados en un arreglo. Dentro del método <code>handleOnSubmit</code>, estamos llamando a la función <code>setBooks</code> pasando un arreglo agregando primero un libro recién agregado y luego extendiendo todos los libros ya agregados en el arreglo de <code>books</code> como se muestra a continuación:</p><pre><code class="language-js">setBooks([book, ...books]);
</code></pre><p>Aquí, estoy agregando el <code>book</code> recién agregad primero y luego extendiendo los <code>books</code> ya agregados porque quiero que el último libro se muestre primero cuando mostremos la lista de libros más tarde.</p><p>Pero puedes cambiar el orden si quieres así:</p><pre><code class="language-js">setBooks([...books, book]);
</code></pre><p>Esto agregará el libro recién agregado al final de todos los libros ya agregados.</p><p>Podemos usar el operador spread porque sabemos que <code>books</code> es un arreglo (ya que lo hemos inicializado a un arreglo vacío <code>[]</code> en el archivo <code>AppRouter.js</code> como se muestra a continuación):</p><pre><code class="language-js"> const [books, setBooks] = useLocalStorage('books', []);
</code></pre><p>Luego, una vez que el libro se agrega al almacenamiento local llamando al método <code>setBooks</code>, dentro del método <code>handleOnSubmit</code> estamos redirigiendo al usuario a la página de <code>Books List</code> utilizando el método <code>history.push</code>:</p><pre><code class="language-js">history.push('/');
</code></pre><p>Ahora verifiquemos si pudimos guardar los libros al almacenamiento local o no.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2021/04/added_local_storage.gif" class="kg-image" alt="added_local_storage" width="600" height="400" loading="lazy"></figure><p>Como puedes ver, el libro se está agregando correctamente al almacenamiento local (y puedes confirmar esto en la pestaña aplicaciones de Chrome dev tools).</p><h2 id="c-mo-mostrar-libros-agregados-en-la-interfaz-de-usuario"><strong>Cómo mostrar libros agregados en la interfaz de usuario</strong></h2><p>Ahora, vamos a mostrar los libros agregados en la interfaz de usuario en el menú <code>Books List</code>.</p><p>Abre el &nbsp;<code>AppRouter.js</code> y pasa los <code>books</code> y <code>setBooks</code> como props al componente <code>BooksList</code>.</p><p>Tu archivo <code>AppRouter.js</code> se verá así ahora:</p><pre><code class="language-jsx">import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Header from '../components/Header';
import AddBook from '../components/AddBook';
import BooksList from '../components/BooksList';
import useLocalStorage from '../hooks/useLocalStorage';

const AppRouter = () =&gt; {
  const [books, setBooks] = useLocalStorage('books', []);

  return (
    &lt;BrowserRouter&gt;
      &lt;div&gt;
        &lt;Header /&gt;
        &lt;div className="main-content"&gt;
          &lt;Switch&gt;
            &lt;Route
              render={(props) =&gt; (
                &lt;BooksList {...props} books={books} setBooks={setBooks} /&gt;
              )}
              path="/"
              exact={true}
            /&gt;
            &lt;Route
              render={(props) =&gt; (
                &lt;AddBook {...props} books={books} setBooks={setBooks} /&gt;
              )}
              path="/add"
            /&gt;
          &lt;/Switch&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/BrowserRouter&gt;
  );
};

export default AppRouter;
</code></pre><p>Aquí, acabamos de cambiar la primera ruto relacionada con el componente <code>BooksList</code>.</p><p>Ahora, crea un nuevo archivo llamado <code>Book.js</code> dentro de la carpeta <code>components</code> con el siguiente contenido:</p><pre><code class="language-jsx">import React from 'react';
import { Button, Card } from 'react-bootstrap';

const Book = ({
  id,
  bookname,
  author,
  price,
  quantity,
  date,
  handleRemoveBook
}) =&gt; {
  return (
    &lt;Card style={{ width: '18rem' }} className="book"&gt;
      &lt;Card.Body&gt;
        &lt;Card.Title className="book-title"&gt;{bookname}&lt;/Card.Title&gt;
        &lt;div className="book-details"&gt;
          &lt;div&gt;Author: {author}&lt;/div&gt;
          &lt;div&gt;Quantity: {quantity} &lt;/div&gt;
          &lt;div&gt;Price: {price} &lt;/div&gt;
          &lt;div&gt;Date: {new Date(date).toDateString()}&lt;/div&gt;
        &lt;/div&gt;
        &lt;Button variant="primary"&gt;Edit&lt;/Button&gt;{' '}
        &lt;Button variant="danger" onClick={() =&gt; handleRemoveBook(id)}&gt;
          Delete
        &lt;/Button&gt;
      &lt;/Card.Body&gt;
    &lt;/Card&gt;
  );
};

export default Book;
</code></pre><p>Ahora, abre el archivo <code>BooksList.js</code> y reemplaza su contenido con el siguiente código:</p><pre><code class="language-jsx">import React from 'react';
import _ from 'lodash';
import Book from './Book';

const BooksList = ({ books, setBooks }) =&gt; {

  const handleRemoveBook = (id) =&gt; {
    setBooks(books.filter((book) =&gt; book.id !== id));
  };

  return (
    &lt;React.Fragment&gt;
      &lt;div className="book-list"&gt;
        {!_.isEmpty(books) ? (
          books.map((book) =&gt; (
            &lt;Book key={book.id} {...book} handleRemoveBook={handleRemoveBook} /&gt;
          ))
        ) : (
          &lt;p className="message"&gt;No books available. Please add some books.&lt;/p&gt;
        )}
      &lt;/div&gt;
    &lt;/React.Fragment&gt;
  );
};

export default BooksList;
</code></pre><p>En este archivo, estamos haciendo un bucle sobre los <code>books</code> usando el método map de arreglo y pasándolos como un prop al componente <code>Book</code>.</p><p>Tenga en cuenta que también estamos pasando la función <code>handleRemoveBook</code> como prop para que podamos eliminar cualquier libro que queramos.</p><p>Dentro de la función <code>handleRemoveBook</code>, estamos llamando a la función <code>setBooks</code> utilizando el método de arreglo <code>filter</code> para solo quedarnos con los libros que no coincidan con el <code>id</code> del libro proporcionado.</p><pre><code class="language-js">const handleRemoveBook = (id) =&gt; {
    setBooks(books.filter((book) =&gt; book.id !== id));
};
</code></pre><p>Ahora si revisas la aplicación ingresando a <a href="http://localhost:3000/">http://localhost:3000/</a>, vas a ver el libro agregado en la interfaz de usuario.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2021/04/list_page.png" class="kg-image" alt="list_page" width="600" height="400" loading="lazy"></figure><p>Agreguemos otro libro para verificar el flujo completo.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2021/04/add_delete.gif" class="kg-image" alt="add_delete" width="600" height="400" loading="lazy"></figure><p>Como puedes ver, cuando agregamos un libro nuevo, nos redirige a la página de listado donde podemos eliminar el libro. Puedes ver que se ha eliminado instantáneamente de la interfaz de usuario como también del almacenamiento local.</p><p>Además, cuando refresquemos la página, los datos no se pierden. Ese es el poder del almacenamiento local.</p><h2 id="c-mo-editar-un-libro"><strong>Cómo editar un libro</strong></h2><p>Ahora tenemos funcionalidad para agregar y borrar los libros. Agreguemos una manera de editar los libros que tenemos.</p><p>Abre <code>Book.js</code> y cambia el código de abajo:</p><pre><code class="language-jsx">&lt;Button variant="primary"&gt;Edit&lt;/Button&gt;{' '}
</code></pre><p>a este código:</p><pre><code class="language-jsx">&lt;Button variant="primary" onClick={() =&gt; history.push(`/edit/${id}`)}&gt;
  Edit
&lt;/Button&gt;{' '}
</code></pre><p>Aquí agregamos un manejador <code>onClick</code> para redirigir al usuario a la ruta <code>/edit/id_of_the_book</code> cuando hacemos clik en el botón editar.</p><p>Pero no tenemos acceso al objeto <code>history</code> dentro del componente <code>Book</code> porque la prop <code>history</code> se pasa solo a los componentes que son mencionados en el <code>&lt;Route /&gt;</code>.</p><p>Estamos renderizando el componente <code>Book</code> dentro del componente <code>BooksList</code> para que podamos tener acceso a <code>history</code> solo dentro del componente <code>BooksList</code>. Después podemos pasarlo como prop al componente <code>Book</code>.</p><p>Pero en lugar de eso, React router nos proporciona una manera fácil utilizando el hook <code>useHistory</code>.</p><p>Importar el hook <code>useHistory</code> al inicio del archivo <code>Book.js</code>:</p><pre><code class="language-js">import { useHistory } from 'react-router-dom';
</code></pre><p>y dentro del componente <code>Book</code>, llamar al hook <code>useHistory</code>.</p><pre><code class="language-js">const Book = ({
  id,
  bookname,
  author,
  price,
  quantity,
  date,
  handleRemoveBook
}) =&gt; {
  const history = useHistory();
  ...
}
</code></pre><p>Ahora tenemos acceso al objeto <code>history</code> dentro del componente <code>Book</code>.</p><p>Tu archivo completo <code>Book.js</code> ahora se ve así:</p><pre><code class="language-jsx">import React from 'react';
import { Button, Card } from 'react-bootstrap';
import { useHistory } from 'react-router-dom';

const Book = ({
  id,
  bookname,
  author,
  price,
  quantity,
  date,
  handleRemoveBook
}) =&gt; {
  const history = useHistory();

  return (
    &lt;Card style={{ width: '18rem' }} className="book"&gt;
      &lt;Card.Body&gt;
        &lt;Card.Title className="book-title"&gt;{bookname}&lt;/Card.Title&gt;
        &lt;div className="book-details"&gt;
          &lt;div&gt;Author: {author}&lt;/div&gt;
          &lt;div&gt;Quantity: {quantity} &lt;/div&gt;
          &lt;div&gt;Price: {price} &lt;/div&gt;
          &lt;div&gt;Date: {new Date(date).toDateString()}&lt;/div&gt;
        &lt;/div&gt;
        &lt;Button variant="primary" onClick={() =&gt; history.push(`/edit/${id}`)}&gt;
          Edit
        &lt;/Button&gt;{' '}
        &lt;Button variant="danger" onClick={() =&gt; handleRemoveBook(id)}&gt;
          Delete
        &lt;/Button&gt;
      &lt;/Card.Body&gt;
    &lt;/Card&gt;
  );
};

export default Book;
</code></pre><p>Crea un nuevo archivo llamado <code>EditBook.js</code> dentro de la carpeta <code>components</code> con el siguiente contenido:</p><pre><code class="language-jsx">import React from 'react';
import BookForm from './BookForm';
import { useParams } from 'react-router-dom';

const EditBook = ({ history, books, setBooks }) =&gt; {
  const { id } = useParams();
  const bookToEdit = books.find((book) =&gt; book.id === id);

  const handleOnSubmit = (book) =&gt; {
    const filteredBooks = books.filter((book) =&gt; book.id !== id);
    setBooks([book, ...filteredBooks]);
    history.push('/');
  };

  return (
    &lt;div&gt;
      &lt;BookForm book={bookToEdit} handleOnSubmit={handleOnSubmit} /&gt;
    &lt;/div&gt;
  );
};

export default EditBook;
</code></pre><p>Aquí para el manejador <code>onClick</code> del botón Edit, estamos redirigiendo al usuario a la ruta <code>/edit/some_id</code> – pero tal ruta todavía no existe. Así que creemos eso primero.</p><p>Abre <code>AppRouter.js</code> y antes de la etiqueta de cierre del <code>Switch</code> agrega dos rutas más:</p><pre><code class="language-jsx">&lt;Switch&gt;
...
&lt;Route
  render={(props) =&gt; (
    &lt;EditBook {...props} books={books} setBooks={setBooks} /&gt;
  )}
  path="/edit/:id"
/&gt;
&lt;Route component={() =&gt; &lt;Redirect to="/" /&gt;} /&gt;
&lt;/Switch&gt;
</code></pre><p>El primer Route es para el componente <code>EditBook</code>. Aquí la ruta se define como <code>/edit/:id</code> donde <code>:id</code> representa cualquier id aleatorio.</p><p>El segundo Route es para manejar todas las otras rutas que no coincidan con alguna de las rutas mencionadas.</p><p>Por lo tanto, si accedemos a cualquier ruta aleatoria como <code>/help</code> o <code>/contact</code> entonces vamos a redirigir al usuario a la ruta <code>/</code> que es el componente <code>BooksList</code>.</p><p>Tu archivo completo <code>AppRouter.js</code> ahora se ve así:</p><pre><code class="language-jsx">import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Header from '../components/Header';
import AddBook from '../components/AddBook';
import BooksList from '../components/BooksList';
import useLocalStorage from '../hooks/useLocalStorage';

const AppRouter = () =&gt; {
  const [books, setBooks] = useLocalStorage('books', []);

  return (
    &lt;BrowserRouter&gt;
      &lt;div&gt;
        &lt;Header /&gt;
        &lt;div className="main-content"&gt;
          &lt;Switch&gt;
            &lt;Route
              render={(props) =&gt; (
                &lt;BooksList {...props} books={books} setBooks={setBooks} /&gt;
              )}
              path="/"
              exact={true}
            /&gt;
            &lt;Route
              render={(props) =&gt; (
                &lt;AddBook {...props} books={books} setBooks={setBooks} /&gt;
              )}
              path="/add"
            /&gt;
            &lt;Route
              render={(props) =&gt; (
                &lt;EditBook {...props} books={books} setBooks={setBooks} /&gt;
              )}
              path="/edit/:id"
            /&gt;
            &lt;Route component={() =&gt; &lt;Redirect to="/" /&gt;} /&gt;
          &lt;/Switch&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/BrowserRouter&gt;
  );
};

export default AppRouter;
</code></pre><p>Ahora verifiquemos la funcionalidad de edición de la aplicación.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2021/04/edit_book.gif" class="kg-image" alt="edit_book" width="600" height="400" loading="lazy"></figure><p>Como podrás ver, podemos editar el libro exitosamente. Entendamos cómo funciona esto.</p><p>Primero, dentro del archivo <code>AppRouter.js</code> tenemos una ruta que se ve así:</p><pre><code class="language-jsx">&lt;Route
  render={(props) =&gt; (
    &lt;EditBook {...props} books={books} setBooks={setBooks} /&gt;
  )}
  path="/edit/:id"
/&gt;
</code></pre><p>y dentro del archivo <code>Book.js</code> tenemos un botón de edición que se ve así:</p><pre><code class="language-jsx">&lt;Button variant="primary" onClick={() =&gt; history.push(`/edit/${id}`)}&gt;
  Edit
&lt;/Button&gt;
</code></pre><p>Entonces, cada vez que hacemos clic en el botón Edit para cualquiera de los libros, estamos redirigiendo al usuario al componente <code>EditBook</code> utilizando el método <code>history.push</code> al pasar el id del libro a ser editado.</p><p>Luego dentro del componente <code>EditBook</code> estamos usando el hook <code>useParams</code> proporcionado por <code>react-router-dom</code> para acceder a <code>props.params.id</code>.</p><p>Por lo tanto las dos líneas de abajo son idénticas.</p><pre><code class="language-js">const { id } = useParams();

// the above line of code is same as the below code

const { id } = props.match.params;
</code></pre><p>Una vez que tengamos ese <code>id</code>, estamos usando el método de arreglo <code>find</code> para encontrar el libro particular de la lista de libros que coincida con el <code>id</code> provisto.</p><pre><code class="language-js">const bookToEdit = books.find((book) =&gt; book.id === id);
</code></pre><p>y este libro particular que estamos pasando al componente <code>BookForm</code> como una prop <code>book</code>:</p><pre><code class="language-jsx">&lt;BookForm book={bookToEdit} handleOnSubmit={handleOnSubmit} /&gt;
</code></pre><p>Dentro del componente <code>BookForm</code>, hemos definido el estado, tal como se muestra abajo:</p><pre><code class="language-js">const [book, setBook] = useState({
  bookname: props.book ? props.book.bookname : '',
  author: props.book ? props.book.author : '',
  quantity: props.book ? props.book.quantity : '',
  price: props.book ? props.book.price : '',
  date: props.book ? props.book.date : ''
});
</code></pre><p>Aquí estamos verificando si la prop <code>book</code> existe. Si existe entonces usaremos los detalles del libro pasado como prop, de lo contrario vamos a inicializar el estado con un valor vacío (<code>''</code>) para cada propiedad.</p><p>Cada uno de los elementos input ha proporcionado una propiedad <code>value</code> la cual estamos fijando desde el estado de esta manera:</p><pre><code class="language-jsx">&lt;Form.Control
  ...
  value={bookname}
  ...
/&gt;
</code></pre><p>Pero podemos mejorar un poco la sintáxis del <code>useState</code> dentro del componente <code>BookForm</code>.</p><p>En vez de fijar directamente un objeto para el hook <code>useState</code>, podemos utilizar inicialización perezosa (<a href="https://reactjs.org/docs/hooks-reference.html#lazy-initial-state">lazy initialization</a>) tal como se hizo en el archivo <code>useLocalStorage.js</code>.</p><p>Entonces cambiemos el código debajo:</p><pre><code class="language-js">const [book, setBook] = useState({
  bookname: props.book ? props.book.bookname : '',
  author: props.book ? props.book.author : '',
  quantity: props.book ? props.book.quantity : '',
  price: props.book ? props.book.price : '',
  date: props.book ? props.book.date : ''
});
</code></pre><p>a este código:</p><pre><code class="language-js">const [book, setBook] = useState(() =&gt; {
  return {
    bookname: props.book ? props.book.bookname : '',
    author: props.book ? props.book.author : '',
    quantity: props.book ? props.book.quantity : '',
    price: props.book ? props.book.price : '',
    date: props.book ? props.book.date : ''
  };
});
</code></pre><p>Debido a este cambio el código para establecer el estado no se ejecutará en cada re-renderización de la aplicación. Solo se ejecutará una vez cuando el componente es montado.</p><blockquote>Tenga en cuenta que la re-renderización de un componente ocurre en cada cambio de estado o propiedades.</blockquote><p>Si verificas la aplicación verás que la aplicación funciona exactamente como lo hizo antes sin ningún problema. Pero hemos mejorado el rendimiento de la aplicación un poco.</p><h2 id="-c-mo-utilizar-la-api-context-de-react"><strong>¿Cómo utilizar la API Context de React?</strong></h2><p>Hemos terminado de armar la funcionalidad de toda la aplicación. Pero si vemos el archivo <code>AppRouter.js</code>, te darás cuenta de que todas las Route se ven un poco complicadas. Esto se debe a que estamos pasando las mismas propiedades <code>books</code> y <code>setBooks</code> a cada uno de los componentes usando el patrón <em>render props</em>.</p><p>Entonces podemos usar la API Context de React para simplificar este código.</p><blockquote>Ten en cuenta que este es un paso opcional. No necesitas utilizar la API Context ya que estamos pasando las props solo un nivel de profundidad y el código actual está funcionando perfectamente y no hemos usado ningún enfoque equivocado para pasar las props.</blockquote><p>Pero solo para que el código Router sea más simple y para darte una idea de como aprovechar el poder de la API Context, vamos a usarlo en nuestra aplicación.</p><p>Crea un nuevo archivo <code>BooksContext.js</code> dentro de la carpeta <code>context</code> con el siguiente contenido:</p><pre><code class="language-js">import React from 'react';

const BooksContext = React.createContext();

export default BooksContext;
</code></pre><p>Ahora dentro del archivo <code>AppRouter.js</code> importa el contexto exportado arriba.</p><pre><code class="language-js">import BooksContext from '../context/BooksContext';
</code></pre><p>y reemplaza el componente <code>AppRouter</code> con el código de abajo:</p><pre><code class="language-jsx">const AppRouter = () =&gt; {
  const [books, setBooks] = useLocalStorage('books', []);

  return (
    &lt;BrowserRouter&gt;
      &lt;div&gt;
        &lt;Header /&gt;
        &lt;div className="main-content"&gt;
          &lt;BooksContext.Provider value={{ books, setBooks }}&gt;
            &lt;Switch&gt;
              &lt;Route component={BooksList} path="/" exact={true} /&gt;
              &lt;Route component={AddBook} path="/add" /&gt;
              &lt;Route component={EditBook} path="/edit/:id" /&gt;
              &lt;Route component={() =&gt; &lt;Redirect to="/" /&gt;} /&gt;
            &lt;/Switch&gt;
          &lt;/BooksContext.Provider&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/BrowserRouter&gt;
  );
};
</code></pre><p>Aquí hemos convertido el patrón render props de vuelta a las rutas normales y agregamos el bloque <code>Switch</code> completo dentro del componente <code>BooksContext.Provider</code> de esta manera:</p><pre><code class="language-jsx">&lt;BooksContext.Provider value={{ books, setBooks }}&gt;
 &lt;Switch&gt;
 ...
 &lt;/Switch&gt;
&lt;/BooksContext.Provider&gt;
</code></pre><p>Aquí, para el componente <code>BooksContext.Provider</code> hemos proporcionado una prop <code>value</code> al pasarle la información que queremos acceder dentro del componente mencionado en el Route.</p><p>Entonces ahora cada componente declarado como parte de Route podrá acceder a <code>books</code> y <code>setBooks</code> por medio de la API Context.</p><p>Ahora abramos el archivo <code>BooksList.js</code> y quitemos las props <code>books</code> y <code>setBooks</code> que son desestructuradas, ya que no estanos pasando directamente las props.</p><p>Importa <code>BooksContext</code> y <code>useContext</code> al inicio del archivo:</p><pre><code class="language-js">import React, { useContext } from 'react';
import BooksContext from '../context/BooksContext';
</code></pre><p>Y arriba de la función <code>handleRemoveBook</code> agrega el siguiente código:</p><pre><code class="language-js">const { books, setBooks } = useContext(BooksContext);
</code></pre><p>Aquí extraemos las props <code>books</code> y <code>setBooks</code> del <code>BooksContext</code> utilizando el hook <code>useContext</code> .</p><p>Tu archivo <code>BooksList.js</code> completo se verá así:</p><pre><code class="language-jsx">import React, { useContext } from 'react';
import _ from 'lodash';
import Book from './Book';
import BooksContext from '../context/BooksContext';

const BooksList = () =&gt; {
  const { books, setBooks } = useContext(BooksContext);

  const handleRemoveBook = (id) =&gt; {
    setBooks(books.filter((book) =&gt; book.id !== id));
  };

  return (
    &lt;React.Fragment&gt;
      &lt;div className="book-list"&gt;
        {!_.isEmpty(books) ? (
          books.map((book) =&gt; (
            &lt;Book key={book.id} {...book} handleRemoveBook={handleRemoveBook} /&gt;
          ))
        ) : (
          &lt;p className="message"&gt;No books available. Please add some books.&lt;/p&gt;
        )}
      &lt;/div&gt;
    &lt;/React.Fragment&gt;
  );
};

export default BooksList;
</code></pre><p>Ahora realicemos cambios similares al archivo <code>AddBook.js</code> .</p><p>Tu archivo <code>AddBook.js</code> completo se verá así:</p><pre><code class="language-jsx">import React, { useContext } from 'react';
import BookForm from './BookForm';
import BooksContext from '../context/BooksContext';

const AddBook = ({ history }) =&gt; {
  const { books, setBooks } = useContext(BooksContext);

  const handleOnSubmit = (book) =&gt; {
    setBooks([book, ...books]);
    history.push('/');
  };

  return (
    &lt;React.Fragment&gt;
      &lt;BookForm handleOnSubmit={handleOnSubmit} /&gt;
    &lt;/React.Fragment&gt;
  );
};

export default AddBook;
</code></pre><p>Ten en cuenta que todavía estamos usando desestructuración para la prop <code>history</code>. Solo hemos eliminado <code>books</code> y <code>setBooks</code> de la sintaxis de desestructuración.</p><p>Ahora hagamos cambios similares al archivo <code>EditBook.js</code> .</p><p>Tu archivo <code>EditBook.js</code> completo se verá así:</p><pre><code class="language-jsx">import React, { useContext } from 'react';
import BookForm from './BookForm';
import { useParams } from 'react-router-dom';
import BooksContext from '../context/BooksContext';

const EditBook = ({ history }) =&gt; {
  const { books, setBooks } = useContext(BooksContext);
  const { id } = useParams();
  const bookToEdit = books.find((book) =&gt; book.id === id);

  const handleOnSubmit = (book) =&gt; {
    const filteredBooks = books.filter((book) =&gt; book.id !== id);
    setBooks([book, ...filteredBooks]);
    history.push('/');
  };

  return (
    &lt;div&gt;
      &lt;BookForm book={bookToEdit} handleOnSubmit={handleOnSubmit} /&gt;
    &lt;/div&gt;
  );
};

export default EditBook;
</code></pre><p>Si verificas la aplicación podrás ver que funciona exactamente como antes, pero ahora estamos utilizando la API Context de React.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/04/edit_delete.gif" class="kg-image" alt="edit_delete" width="600" height="400" loading="lazy"></figure><blockquote>Si quieres entender la API Context en detalle echa un vistazo a <a href="https://medium.com/swlh/what-is-context-api-in-react-and-how-to-use-it-in-react-app-dedbcdd78801">mi artículo</a>.</blockquote><h3 id="gracias-por-leer-"><strong>Gracias por leer<strong>!</strong></strong></h3><p>Puedes encontrar el código fuente completo para esta aplicación en <a href="https://github.com/myogeshchavan97/react-book-management-app">este repositorio</a>.</p><p>¿Quieres aprender todas las características de ES6+ en detalle desde cero incluyendo let y const, promesas, varios métodos de promesas, desestructuración de arreglos y objetos, funciones flechas, async/await, import y export y un montón más?</p><p><strong>Echa un vistazo a mi libro <strong><a href="https://modernjavascript.yogeshchavan.dev/">Mastering Modern JavaScript</a>. </strong>Este libro cubre todos los prerrequisitos para aprender React y te ayuda a mejorar en JavaScript y React<strong>.</strong></strong></p><blockquote>Echa un vistazo a una vista previa del contenido del libro <a href="https://www.freecodecamp.org/news/learn-modern-javascript/">aquí</a>.</blockquote><p>También puedes ver mi curso gratuito <a href="https://yogeshchavan1.podia.com/react-router-introduction">Introducción a React Router</a> para aprender desde cero React Router.</p><p>¿Quieres mantenerte actualizado con contenido relacionado con JavaScript, React, Node.js? <a href="https://www.linkedin.com/in/yogesh-chavan97/">Sígueme en LinkedIn</a>.</p><figure class="kg-card kg-image-card"><img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg" class="kg-image" alt="banner" width="600" height="400" loading="lazy"></figure> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Aprende las bases de HTML para principiantes en solo 15 minutos ]]>
                </title>
                <description>
                    <![CDATA[ Si quieres crear un sitio web, el primer lenguaje que necesitas aprender es HTML. Artículo original escrito por Thu Nghiem [https://www.freecodecamp.org/news/author/thu/] Artículo original Learn HTML Basics for Beginners in Just 15 Minutes [https://www.freecodecamp.org/news/html-basics-for-beginners/] Traducido y adaptado por Ezequiel Castellanos [/espanol/news/author/ezequiel_caste/] En este artículo vamos a repasar los conceptos básicos de ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/aprende-las-bases-de-html-para-principiantes-en-solo-15-minutos/</link>
                <guid isPermaLink="false">60d609820703cb0926dc770c</guid>
                
                    <category>
                        <![CDATA[ Desarrollo Web ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Mon, 09 Aug 2021 10:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/08/Ep10_html.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="si-quieres-crear-un-sitio-web-el-primer-lenguaje-que-necesitas-aprender-es-html-">Si quieres crear un sitio web, el primer lenguaje que necesitas aprender es HTML.</h2><p><br><strong>Artículo original escrito por</strong> <a href="https://www.freecodecamp.org/news/author/thu/">Thu Nghiem</a><br><strong>Artículo original </strong><a href="https://www.freecodecamp.org/news/html-basics-for-beginners/">Learn HTML Basics for Beginners in Just 15 Minutes</a><br><strong>Traducido y adaptado por</strong> <a href="https://www.freecodecamp.org/espanol/news/author/ezequiel_caste/">Ezequiel Castellanos</a></p><p>En este artículo vamos a repasar los conceptos básicos de HTML. Al final vamos a crear un sitio web básico utilizando únicamente HTML.</p><p>Aquí hay un video que puedes ver si quieres complementar este artículo:‌‌</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.17932432432432%;" class="fluid-width-video-wrapper">
            <iframe src="https://www.youtube.com/embed/pMJ0NI3OkYA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" name="fitvid0" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; position: absolute; top: 0px; left: 0px; width: 740px; height: 415.727px;"></iframe>
          </div>
        </div>
      </figure><p></p><h2 id="-qu-es-html"><strong>¿Qué es<strong> HTML?</strong></strong></h2><p>HTML, cuyas siglas significan Lenguaje de Marcado de Hipertexto (Hypertext Markup Languaje), es un lenguaje bastante simple. Consiste en distintos elementos que utilizamos para estructurar una página web.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/2_1_cr.png" class="kg-image" alt="2_1_cr" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/2_1_cr.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/08/2_1_cr.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/08/2_1_cr.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/size/w2400/2021/08/2_1_cr.png 2400w" sizes="(min-width: 1200px) 1200px" width="2000" height="1250" loading="lazy"><figcaption>¿Qué es HTML?</figcaption></figure><h2 id="-qu-son-los-elementos-html"><strong>¿Qué son los elementos <strong>HTML?</strong></strong></h2><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/Elemento-HTML_cr.png" class="kg-image" alt="Elemento-HTML_cr" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/Elemento-HTML_cr.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/08/Elemento-HTML_cr.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/08/Elemento-HTML_cr.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/size/w2400/2021/08/Elemento-HTML_cr.png 2400w" sizes="(min-width: 1200px) 1200px" width="2000" height="1257" loading="lazy"><figcaption>Elementos HTML</figcaption></figure><p>El elemento normalmente comienza con una etiqueta de apertura, la cual consiste en el nombre del elemento. Se rodean (Es contenida) por corchetes angulares de apertura y cierre. La etiqueta de apertura indica dónde comienza el elemento.</p><p>De igual manera que la etiqueta de apertura, la etiqueta de cierre también está contenida por corchetes angulares de apertura y cierre. Pero también incluye una barra antes del nombre del elemento.</p><p>Todo lo que está dentro de las etiquetas de apertura y cierre es el contenido.</p><p>Pero no todos los elementos siguen este patrón. Les decimos elementos vacíos a aquellos que no siguen este patrón. Estos únicamente consisten en una etiqueta simple o una etiqueta de apertura que no puede tener ningún contenido. Estos elementos se utilizan normalmente para insertar algo en el documento.</p><p>Por ejemplo, el elemento <code>&lt;img&gt;</code> es utilizado para insertar un archivo de imagen, o el elemento <code>&lt;input&gt;</code> es utilizado para insertar un campo de datos en la página.</p><pre><code class="language-html">&lt;img src="https://images.unsplash.com/photo-1610447847416-40bac442fbe6" width="50"&gt;</code></pre><p>En el ejemplo de arriba, el elemento <code>&lt;img&gt;</code> sólo consiste en una etiqueta que no tiene ningún contenido. Este elemento es usado para insertar en el documento un archivo de imagen desde <a href="https://unsplash.com/">Unsplash</a>.</p><h2 id="como-anidar-elementos-html"><strong>Como anidar elementos <strong>HTML</strong></strong></h2><pre><code class="language-html">&lt;div class="my-list"&gt;
  &lt;h4&gt;My list:&lt;/h4&gt;

  &lt;ul&gt;
     &lt;li&gt;Apple&lt;/li&gt;
     &lt;li&gt;Orange&lt;/li&gt;
     &lt;li&gt;Banana&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
</code></pre><p>Los elementos pueden ser colocados dentro de otros elementos. Esto se llama Anidamiento. En el ejemplo de arriba, dentro del elemento <code>&lt;div&gt;</code> tenemos un elemento <code>&lt;h4&gt;</code> y un elemento <code>&lt;ul&gt;</code> o elemento de lista no ordenado. De manera similar dentro del elemento <code>&lt;ul&gt;</code> hay 3 elementos <code>&lt;li&gt;</code> o elemento de lista.</p><p>El anidamiento básico es bastante sencillo de entender. Pero cuando la página crece, el anidamiento puede complicarse.</p><p>Por lo tanto, antes de trabajar con HTML, piensa sobre la estructura de diseño que te gustaría tener. Puedes dibujarla en un papel o en tu mente. Será de mucha ayuda.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/3_1_cr.png" class="kg-image" alt="3_1_cr" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/3_1_cr.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/08/3_1_cr.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/08/3_1_cr.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/size/w2400/2021/08/3_1_cr.png 2400w" sizes="(min-width: 1200px) 1200px" width="2000" height="1250" loading="lazy"></figure><h2 id="-qu-son-los-atributos-html"><strong>¿Qué son los atributos HTML<strong>?</strong></strong></h2><p>Los elementos también tienen atributos que contienen información adicional acerca del elemento que no aparecerá en el contenido.</p><pre><code class="language-html">&lt;img src="https://images.unsplash.com/photo" width="50"&gt;</code></pre><p>En el ejemplo de arriba, el elemento <code>&lt;img&gt;</code> tiene 2 atributos: <code>src</code> u origen para especificar la ruta de la imagen, y <code>width</code> para especificar el ancho de la imagen en pixeles.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/4_1_cr.png" class="kg-image" alt="4_1_cr" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/4_1_cr.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/08/4_1_cr.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/08/4_1_cr.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/size/w2400/2021/08/4_1_cr.png 2400w" sizes="(min-width: 1200px) 1200px" width="2000" height="1248" loading="lazy"></figure><p>Con este ejemplo, puedes ver las siguientes características o atributos:</p><ul><li>Hay un espacio entre atributo y el nombre del elemento</li><li>Los atributos se agregan en la etiqueta de apertura</li><li>Los elementos pueden tener varios atributos</li><li>Los atributos tienen un nombre y un valor: nombre=“valor”</li></ul><p>Pero no todos los atributos tienen el mismo patrón. Algunos pueden existir sin valores y les decimos Atributos Booleanos.</p><pre><code class="language-html">&lt;button onclick=“alert('Submit')" disabled&gt;Button&lt;/button&gt;</code></pre><p>En este ejemplo, si queremos desactivar el botón, lo único que tenemos que hacer es pasar un atributo <code>disabled</code> sin ningún valor. Esto significa que la presencia del atributo representa el valor verdadero, de lo contrario, la ausencia representa el valor falso.</p><h3 id="elementos-comunes-de-html"><strong>Elementos comunes de <strong>HTML</strong></strong></h3><p>Existen en total más de 100 elementos. Pero 90% del tiempo sólo vas a utilizar alrededor de 20 de los más comunes. Los he colocado en 5 grupos:</p><h4 id="elementos-de-secci-n"><strong>Elementos de sección</strong></h4><pre><code class="language-html">  &lt;div&gt;, &lt;span&gt;, &lt;header&gt;, &lt;footer&gt;, &lt;nav&gt;, &lt;main&gt;, &lt;section&gt; 
</code></pre><p>Estos elementos se utilizan para organizar el contenido en diferentes secciones. Por lo general son muy obvios, por ejemplo<code>&lt;header&gt;</code> representa a un grupo de la sección de introducción y navegación, <code>&lt;nav&gt;</code> representa la sección que contiene los enlaces de navegación, etcétera.</p><h4 id="contenido-de-texto"><strong>Contenido de texto</strong></h4><pre><code class="language-html">  &lt;h1&gt; to &lt;h6&gt;, &lt;p&gt;, &lt;div&gt;, &lt;span&gt;, &lt;ul&gt;, &lt;ol&gt;, &lt;li&gt;
</code></pre><p>Estos elementos se utilizan para organizar contenido o bloques de texto. Son importantes para la accesibilidad y posicionamiento en buscadores (SEO). Estos le comunican al navegador el propósito o estructura del contenido.</p><h4 id="formularios"><strong>Formularios</strong></h4><pre><code class="language-html">  &lt;form&gt;, &lt;input&gt;, &lt;button&gt;, &lt;label&gt;, &lt;textarea&gt;
</code></pre><p>Estos elementos pueden utilizarse juntos para crear formularios que los usuarios pueden completar y enviar. Los formularios pueden ser la parte más complicada de HTML.</p><h4 id="im-genes-y-enlaces">Imágenes<strong> y enlaces</strong></h4><pre><code class="language-html">  &lt;img&gt;, &lt;a&gt;
</code></pre><p>Estos elementos se utilizan para insertar una imagen o crear un hipervínculo.</p><h4 id="otros"><strong><strong>Otr</strong>o<strong>s</strong></strong></h4><pre><code class="language-html">  &lt;br&gt;, &lt;hr&gt;
</code></pre><p>Estos elementos se utilizan para agregar un quiebre a la página web.</p><p>Puedes encontrar todos los elementos en <a href="https://developer.mozilla.org/es/docs/Web/HTML/Element">developer.mozilla.org</a>. Pero para principiantes, sólo necesitas conocer los más comunes.</p><h2 id="elementos-html-de-nivel-bloque-vs-en-l-nea"><strong>Elementos <strong>HTML</strong> de nivel bloque vs en línea</strong></h2><p>De manera predeterminada un elemento puede ser un elemento de nivel bloqué o en línea.</p><p>Elementos de nivel bloqué son los elementos que siempre comienzan en una nueva línea y ocupan todo el ancho disponible.</p><p>Elementos en línea son los elementos que no comienzan en una nueva línea y sólo ocupan tanto ancho como sea necesario.‌‌</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/5_cr.png" class="kg-image" alt="5_cr" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/5_cr.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/08/5_cr.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/08/5_cr.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/size/w2400/2021/08/5_cr.png 2400w" sizes="(min-width: 1200px) 1200px" width="2000" height="1252" loading="lazy"><figcaption>Elementos de nivel Bloque vs En Línea</figcaption></figure><p>Dos elementos que representan elementos de nivel bloqué y elementos en línea, respectivamente, son <code>&lt;div&gt;</code> y <code>&lt;span&gt;</code>. En este ejemplo puedes ver que el elemento <code>&lt;div&gt;</code> ocupa 3 líneas, mientras que el elemento <code>&lt;span&gt;</code> solo ocupa 1 línea.</p><p>Pero la pregunta es: ¿Cómo sabemos cuáles son elementos a nivel de bloqué y cuáles son elementos en línea? Bueno, desafortunadamente necesitas recordarlos. La forma más sencilla es recordar cuáles son elementos en línea y el si resto son elementos de bloqué. </p><p>Si recordamos los elementos HTML más comunes, los elementos en línea incluyen: <code>&lt;span&gt;, &lt;input&gt;, &lt;button&gt;, &lt;label&gt;, &lt;textarea&gt;, &lt;img&gt;, &lt;a&gt;, &lt;br&gt;</code>.</p><h2 id="-c-mo-comentar-en-html"><strong>¿Cómo comentar en <strong>HTML</strong>?</strong></h2><pre><code class="language-html">&lt;p&gt;This is a paragraph.&lt;/p&gt;

&lt;!-- &lt;p&gt;I am not showing.&lt;/p&gt; --&gt;
</code></pre><p>El propósito de los comentarios es incluir notas en el código para explicar la lógica o simplemente para organizar tu código.</p><p>Los comentarios HTML están contenidos por marcadores especiales: <code>&lt;!-- y --&gt;</code> y son ignorados en el navegador.</p><h2 id="como-utilizar-entidades-html"><strong>Como utilizar entidades <strong>HTML</strong></strong></h2><p>¿Qué pasa si quieres mostrar el texto: <code>la etiqueta &lt;p&gt; define un párrafo.</code>, pero el navegador interpreta <code>&lt;p&gt;</code> como una etiqueta de apertura para un nuevo elemento? En este caso, podemos usar entidades de caracteres HTML como en el siguiente ejemplo:</p><pre><code class="language-html">&lt;p&gt;the &lt;p&gt; tag defines a paragraph.&lt;/p&gt;

&lt;p&gt;the &amp;lt;p&amp;gt; define a paragraph.&lt;/p&gt;
</code></pre><h2 id="c-mo-utilizar-emoji-en-html"><strong>Cómo utilizar emoji en <strong>HTML</strong></strong></h2><p>En la web moderna, podemos mostrar emoji en HTML de manera bastante fácil, así: ?</p><pre><code class="language-html">&lt;p&gt;? Cara Sonriente.&lt;/p&gt;

&lt;p&gt;? Cumpleaños&lt;/p&gt;
</code></pre><h2 id="errores-comunes-de-principiantes-en-html"><strong>Errores comunes de principiantes en <strong>HTML</strong></strong></h2><h3 id="1-nombres-de-etiquetas-elementos"><strong><strong>1. </strong>Nombres de Etiquetas/Elementos</strong></h3><p>Los nombres de las etiquetas/elementos no no distinguen entre mayúsculas y minúsculas. Esto significa que se pueden escribir en minúscula o mayúscula, pero se recomienda que escribas todo en minúscula: <code>&lt;button&gt;</code> no <code>&lt;ButTon&gt;</code>.</p><h3 id="2-etiqueta-de-cierre"><strong><strong>2. </strong>Etiqueta de cierre</strong></h3><p>No incluir la etiqueta de cierre es un error común de principiante. Por lo tanto, cuando estés creando una etiqueta de apertura, inmediatamente agrega la etiqueta de cierre.</p><h3 id="3-anidado"><strong><strong>3. </strong>Anidado</strong></h3><p>Esto está mal:</p><pre><code class="language-html">&lt;div&gt;Div 1 &lt;span&gt; Span 2 &lt;/div&gt;&lt;/span&gt;
</code></pre><p>Las etiquetas &nbsp;tienen que abrirse y cerrarse de tal forma que queden dentro o fuera de las otras.</p><h3 id="4-comillas-simples-o-comillas-dobles"><strong>4. Comillas simples o Comillas dobles</strong></h3><p>Esto está mal:</p><pre><code class="language-html">&lt;img src="https://images.unsplash.com/'&gt;
</code></pre><p>No se pueden mezclar comillas simples con comillas dobles. Siempre deberías usar comillas dobles y usar entidades HTML si fuera necesario.</p><h2 id="-c-mo-crear-un-sitio-web-simple-con-html"><strong>¿Cómo crear un sitio web simple con HTML?</strong></h2><p>Los elementos HTML individuales no son suficientes como para crear un sitio web. Entonces veamos qué más necesitamos para crear un sitio web simple desde cero.</p><h3 id="-c-mo-crear-un-documento-html"><strong>¿Cómo crear un documento HTML?</strong></h3><p>Primero, abramos <a href="https://code.visualstudio.com/">Visual Studio Code</a> (o tu editor de código favorito). En la carpeta que elijas, crea un nuevo archivo y dale el nombre de index.html.</p><p>En el archivo index.html, escribe! (signo de exclamación) y presiona enter. Vas a ver algo como esto:</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>Esto es el código mínimo que un documento HTML debe tener para armar un sitio web. Aquí tenemos:</p><ol><li><code>&lt;!DOCTYPE html&gt;</code>: Primero tenemos Doctype. Por alguna extraña razón histórica tenemos que incluir el doctype para que todo funcione correctamente.</li><li><code>&lt;html lang="en"&gt;&lt;/html&gt;</code>: El elemento<code>&lt;html&gt;</code> envuelve todo el contenido de la página, también conocido como el elemento raíz. Siempre debemos incluir el atributo <code>lang</code> para declarar el idioma de la página.</li><li><code>&lt;head&gt;&lt;/head&gt;</code>: El elemento <code>&lt;head&gt;</code> es un contenedor para todo lo que quieras incluir pero no contenido que muestres a tus usuarios.</li><li><code>&lt;meta charset="UTF-8" /&gt;</code>: El primer elemento meta es utilizado para establecer el set de caracteres para que sea UTF-8, el cual incluye la mayoría de los caracteres del lenguaje escrito.</li><li><code>&lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;</code>: El segundo elemento meta especifica el viewport del navegador. Esta configuración es para un sitio web optimizado para dispositivos móviles.</li><li><code>&lt;title&gt;Document&lt;/title&gt;</code>: Este es el elemento <code>&lt;title&gt;</code>. Establece el título de la página.</li><li><code>&lt;body&gt;&lt;/body&gt;</code>: El elemento <code>&lt;body&gt;</code> contiene todo el contenido en la página.</li></ol><h3 id="-c-mo-crear-una-p-gina-de-recetas-de-panqueques"><strong>¿Cómo crear una </strong>página de recetas de panqueques?</h3><p>Bien, ahora que tenemos el código inicial creemos la página de recetas de panqueques. Vamos a usar el contenido de la página <a href="https://www.allrecipes.com/recipe/21014/good-old-fashioned-pancakes/">AllRecipes</a>.</p><p>Primero, vamos a darle al elemento <code>&lt;title&gt;</code> contenido de la receta de panqueques. Vas a ver cambiar el texto en la pestaña de la página web. En el elemento <code>&lt;body&gt;</code>, creamos 3 elementos: <code>&lt;header&gt;</code>, <code>&lt;main&gt;</code> y <code>&lt;footer&gt;</code> que representan las 3 secciones.</p><h4 id="1-crear-la-secci-n-de-encabezado"><strong>1. Crear la sección de encabezado</strong></h4><p>En el encabezado, queremos tener el logo y la navegación. Por lo tanto, vamos a crear un <code>div</code> con el contenido <code>ALL RECIPE</code> para el logo.</p><p>Para la navegación, usemos el elemento <code>&lt;nav&gt;</code>. Dentro del elelmento <code>&lt;nav&gt;</code>, podemos usar <code>&lt;ul&gt;</code> para crear una lista desordenada. Queremos tener 3 elementos <code>&lt;li&gt;</code> para 3 enlaces: Ingredientes, Pasos, y Suscribirse. El código del encabezado se ve así:</p><pre><code class="language-html">...
    &lt;header&gt;
      &lt;div&gt;ALL RECIPE&lt;/div&gt;
      &lt;nav&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href="#ingredients"&gt;Ingredientes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href="#steps"&gt;Pasos&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href="#subsribe"&gt;Suscribirse&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/nav&gt;
    &lt;/header&gt;
...
</code></pre><h4 id="2-crear-la-secci-n-principal"><strong>2. Crear la sección principal</strong></h4><p>En la sección main, primero, queremos tener un título y una imagen. Podemos usar <code>h1</code> para el título y <code>&lt;img&gt;</code> para la imagen (podemos usar una imagen desde <a href="https://images.unsplash.com/">Unsplash</a> gratis):</p><pre><code class="language-html">...
    &lt;main&gt;
      &lt;h1&gt;Panqueques Clásicos&lt;/h1&gt;
      &lt;img
        src="https://images.unsplash.com/photo-1575853121743-60c24f0a7502"
        alt="pancake"
        width="250"
      /&gt;
    &lt;/main&gt;
...
</code></pre><p>Después, queremos listar todos los ingredientes. Podemos usar <code>&lt;ol&gt;</code> para crear una lista ordenada y <code>&lt;input type="checkbox" /&gt;</code> para crear una casilla de verificación.</p><p>Pero antes de esto, podemos usar <code>&lt;h2&gt;</code> para comenzar un nuevo bloque de contenido. También vamos a agregar el atributo <code>id</code> para el <code>&lt;h2&gt;</code> para que el enlace en la navegación sepa donde ir:</p><pre><code class="language-html">...
    &lt;main&gt;
    ...
      &lt;h2 id="ingredients"&gt;Ingredientes&lt;/h2&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 ½ tazas de harina para todo uso&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 3 ½ cucharaditas de levadura en polvo&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 cucharadita de sal&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 cucharada de azucar blanca&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 ¼ tazas de leche&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 huevo&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/main&gt;
...
</code></pre><p>Después de los ingredientes, vamos a listar todos los pasos. Podemos usar <code>&lt;h4&gt;</code> para el encabezado de los pasos y <code>&lt;p&gt;</code> para el contenido de los pasos:</p><pre><code class="language-html">...
    &lt;main&gt;
    ...
      &lt;h2 id="steps"&gt;Pasos&lt;/h2&gt;
      
      &lt;h4&gt;Paso 1&lt;/h4&gt;
      &lt;p&gt;
        En un tazón grande, tamice la harina, el polvo de hornear, la sal y el azúcar.
        Hacer un hueco en el centro y verter la leche, el huevo y la mantequilla derretida;
        mezclar hasta que quede suave.
      &lt;/p&gt;
      
      &lt;h4&gt;Paso 2&lt;/h4&gt;
      &lt;p&gt;
        Caliente una plancha o sartén ligeramente engrasada a fuego medio-alto.
        Verter o coloque la masa en la plancha, usando aproximadamente 1/4 taza para cada panqueque.
          Dorar por ambos lados y servir caliente.
      &lt;/p&gt;
    &lt;/main&gt;
...
</code></pre><p>Bien, ahora que hemos terminado con la sección principal, sigamos con la sección pie de página.</p><h4 id="3-crear-la-secci-n-pie-de-p-gina"><strong>3. Crear la sección pie de página</strong></h4><p>En el pie de página queremos tener el formulario de suscripción y el texto de derechos de autor.</p><p>Para el formulario de suscripción, podemos usar el elemento <code>&lt;form&gt;</code>. Dentro podemos tener un <code>&lt;input type="text"&gt;</code> para la entrada de texto y un botón <code>&lt;button&gt;</code> para el botón de enviar.</p><p>Para el texto de derechos de autor, simplemente podemos usar un <code>&lt;div&gt;</code>. Tome nota aquí, podemos usar la entidad HTML <code>$copy;</code> para el símbolo de copyright.</p><p>Podemos incluir un <code>&lt;br&gt;</code> para agregar espacio entre el formulario de suscripción y el texto copyright:</p><pre><code class="language-html">...
    &lt;footer&gt;
      &lt;h6 id="subscribe"&gt;Suscribirse&lt;/h6&gt;
      &lt;form onsubmit="alert('Suscrito')"&gt;
        &lt;input type="text" placeholder="Ingrese Email" /&gt;
        &lt;button&gt;Enviar&lt;/button&gt;
      &lt;/form&gt;
      &lt;br /&gt;
      &lt;div&gt;&amp;copy; dakota kelly en Allrecipe.com&lt;/div&gt;
    &lt;/footer&gt;
...
</code></pre><p>Bien, ahora hemos terminado! Aquí está el código completo para referencia:</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;title&gt;Receta para Panqueques&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;header&gt;
      &lt;div&gt;ALL RECIPE&lt;/div&gt;
      &lt;nav&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href="#ingredients"&gt;Ingredientes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href="#steps"&gt;Pasos&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href="#subsribe"&gt;Suscribirse&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/nav&gt;
    &lt;/header&gt;
    &lt;main&gt;
      &lt;h1&gt;Panqueques Clásicos&lt;/h1&gt;
      &lt;img
        src="https://images.unsplash.com/photo-1575853121743-60c24f0a7502?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8cGFuY2FrZXxlbnwwfHwwfA%3D%3D&amp;ixlib=rb-1.2.1&amp;auto=format&amp;fit=crop&amp;w=700&amp;q=60"
        alt="pancake"
        width="250"
      /&gt;
      &lt;h2 id="ingredients"&gt;Ingredientes&lt;/h2&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 ½ tazas de harina para todo uso&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 3 ½ cucharaditas de levadura en polvo&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 cucharadita de sal&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 cucharada de azucar blanca&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 ¼ tazas de leche&lt;/li&gt;
        &lt;li&gt;&lt;input type="checkbox" /&gt; 1 huevo&lt;/li&gt;
      &lt;/ol&gt;    
      &lt;h2 id="steps"&gt;Pasos&lt;/h2&gt;
      
      &lt;h4&gt;Paso 1&lt;/h4&gt;
      &lt;p&gt;
        En un tazón grande, tamice la harina, el polvo de hornear, la sal y el azúcar.
        Hacer un hueco en el centro y verter la leche, el huevo y la mantequilla derretida;
        mezclar hasta que quede suave.
      &lt;/p&gt;
      
      &lt;h4&gt;Paso 2&lt;/h4&gt;
      &lt;p&gt;
        Caliente una plancha o sartén ligeramente engrasada a fuego medio-alto.
        Verter o coloque la masa en la plancha, usando aproximadamente 1/4 taza para cada panqueque.
          Dorar por ambos lados y servir caliente.
      &lt;/p&gt;
    &lt;/main&gt;
    &lt;hr /&gt;
    &lt;footer&gt;
      &lt;h6 id="subscribe"&gt;Suscribirse&lt;/h6&gt;
      &lt;form onsubmit="alert('Suscrito')"&gt;
        &lt;input type="text" placeholder="Ingrese Email" /&gt;
        &lt;button&gt;Enviar&lt;/button&gt;
      &lt;/form&gt;
      &lt;br /&gt;
      &lt;div&gt;&amp;copy; dakota kelly en Allrecipe.com&lt;/div&gt;
    &lt;/footer&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre><h2 id="conclusi-n"><strong>Conclusión</strong></h2><p>Puedes crear un sitio web simple con solo HTML. Pero para poder construir sitios web hermosos y funcionales, necesitas estudiar CSS y JavaScript.</p><p>Me puedes seguir en redes sociales o Youtube para actualizaciones futuras sobre estos temas. Pero mientras tanto, puedes chequear el Plan de Estudios de <a href="https://www.freecodecamp.org/espanol/learn/">freeCodeCamp</a> para practicar HTML resolviendo pequeñas tareas.</p><p>Si no, puedes seguir codeando y nos vemos en futuros posts ?.<br><br>__________ ? Acerca de mí __________</p><ul><li>Soy el fundador de <a href="https://devchallenges.io/">DevChallenges</a></li><li>Suscríbete a <a href="https://www.youtube.com/c/thunghiem">mi Canal</a></li><li>Sigue mi<a href="https://twitter.com/thunghiemdinh"> Twitter</a></li><li>Únete al <a href="https://discord.com/invite/3R6vFeM">Discord</a></li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Mi lista de consejos de GitHub y aplicaciones de terceros que me ayudan a mantenerme productivo ]]>
                </title>
                <description>
                    <![CDATA[ Trabajo en Thinkific con otros 20+ desarrolladores (estamos contratando para varios puestos de trabajo) en distintas bases de código. GitHub es parte de nuestro kit de herramientas, y decidí escribir una publicación compartiendo algunas extensiones de Chrome, integraciones y aplicaciones de terceros que me ayudan a ser productivo como colaborador ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/mi-lista-de-consejos-github-y-aplicaciones-de-terceros-que-me-ayudan-a-mantenerme-productivo/</link>
                <guid isPermaLink="false">5ffb1b578c7cd154bb98617b</guid>
                
                    <category>
                        <![CDATA[ Productividad ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Fri, 05 Mar 2021 06:51:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/04/photo-1497032628192-86f99bcd76bc.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Trabajo en Thinkific con otros 20+ desarrolladores (estamos contratando para varios puestos de trabajo) en distintas bases de código. GitHub es parte de nuestro kit de herramientas, y decidí escribir una publicación compartiendo algunas extensiones de Chrome, integraciones y aplicaciones de terceros que me ayudan a ser productivo como colaborador individual y organizado como revisor de código y líder de equipo.</p><h2 id="extensiones-de-chrome"><strong>Extensiones de Chrome</strong></h2><h3 id="refined-github"><strong><a href="https://chrome.google.com/webstore/detail/refined-github/hlepfoohegkhhmjieoechaddaejaokhf?hl=en">Refined GitHub</a></strong></h3><p>La extensión de <a href="https://sindresorhus.com/">Sindre Sorhus</a> trae una <a href="https://github.com/sindresorhus/refined-github#repositories">lista masiva de mejoras</a> a la interfaz de usuario de GitHub y muchas de ellas han formado parte del producto después de un tiempo. GOAT (El Mejor del Mundo). Muchas veces un colega pasó por mi computadora y dijo "Oh, GitHub cambió esto" pero en realidad es una mejora de Refined GitHub.</p><h3 id="better-pull-request-for-github"><strong><a href="https://chrome.google.com/webstore/detail/better-pull-request-for-g/nfhdjopbhlggibjlimhdbogflgmbiahc?hl=en">Better Pull Request for GitHub</a></strong></h3><p>Esta extensión enumera los archivos del proyecto en un árbol. Esto es bastante útil cuando tienes un gran pedido de descarga y necesitas ir y venir para comprender mejor lo que está sucediendo.</p><figure class="kg-card kg-image-card"><img src="https://leonardofaria.net/wp-content/uploads/2019/09/better-pull-request-for-github.jpg" class="kg-image" alt="better-pull-request-for-github" width="640" height="400" loading="lazy"></figure><h3 id="github-hovercard"><strong><a href="https://chrome.google.com/webstore/detail/github-hovercard/mmoahbbnojgkclgceahhakhnccimnplk?hl=en">GitHub Hovercard</a></strong></h3><p>Esta extensión muestra información sobre un usuario, proyecto, problema o commit. Es un truco de UI genial como lo hace Facebook. Esta extensión incluso funciona para repositorios privados, siempre que tenga un token válido para obtener la información del servicio.</p><figure class="kg-card kg-image-card"><img src="https://leonardofaria.net/wp-content/uploads/2019/09/hover-cards.jpg" class="kg-image" alt="hover-cards" width="640" height="400" loading="lazy"></figure><h3 id="github-repository-size"><strong><a href="https://chrome.google.com/webstore/detail/github-repository-size/apnjnioapinblneaedefcnopcjepgkci?hl=en">GitHub Repository Size</a></strong></h3><p>Esta extensión agrega automáticamente el tamaño del repositorio y el tamaño de los archivos individuales.</p><h3 id="file-icon-for-github-and-gitlab"><strong><a href="https://chrome.google.com/webstore/detail/file-icon-for-github-and/ficfmibkjjnpogdcfhfokmihanoldbfe">File Icon for GitHub and GitLab</a></strong></h3><p>No hay mucho que decir aquí :)</p><h2 id="integraciones">Integraciones</h2><h3 id="pull-panda"><strong><a href="https://pullpanda.com/">Pull Panda</a></strong></h3><p>Pull Panda es una integración que GitHub adquirió <a href="https://pullpanda.com/github">hace unos meses atrás</a> y que han agregado gratuitamente en el producto. Es muy útil porque puedes asignar usuarios de GitHub a usuarios de Slack y luego obtener toda la información dentro de Slack sobre el trabajo que están siguiendo en Slack. Pull Panda entrega comentarios en PRS e incluso te informa sobre conflictos de git (me encanta y odio esto).</p><p>Pull Panda también puede detectar cuellos de botellas, indica quienes son los que más hacen subidas/revisión de código, e incluso automáticamente asigna personas a los pedidos de descarga.</p><h2 id="macos-apps"><strong>macOS apps</strong></h2><h3 id="gitify"><strong><a href="https://www.gitify.io/">Gitify</a></strong></h3><p>Gitify vive en la barra de menú de tu Mac y es bastante simple de entender. Si el icono es verde, tienes una notificación! También es interesante mencionar que la aplicación es de <a href="https://github.com/manosim/gitify">código abierto</a> (basada en Electro, si eres curioso)</p><h3 id="quests"><strong><a href="https://steamclock.com/quests/">Quests</a></strong></h3><p>Quests es similar a Gitify pero con una diferencia importante: Quest también soporta GitLab.</p><h3 id="devhub"><strong><a href="https://devhubapp.com/">DevHub</a></strong></h3><p>DevHub es una aplicación multiplataforma (iOS, Android, macOS, Windows, Linux) similar a TweetDeck, pero para GitHub. No soy un gran fanático de las aplicaciones de múltiples columnas como TweetDeck, pero es importante mencionar que la aplicación también se ejecuta como una aplicación de barra de menú como Gitify o Quest.</p><h2 id="aplicaciones-ios"><strong>Aplicaciones iOS</strong></h2><h3 id="githawk"><strong><a href="http://githawk.com/">Githawk</a></strong></h3><p>Githawk es mi aplicación de iOS favorita para GitHub. Enumera las solicitudes de descarga de manera amigable y me gusta cómo puedes ver los archivos afectados en el PR y todas las conversaciones en su lugar. Si necesitas echar un vistazo a una solicitud de descarga cuando no estás frente a la computadora, ¡esta aplicación es para tí! </p><h3 id="github-for-mobile"><strong><a href="https://github.com/mobile">GitHub for Mobile</a></strong></h3><p>En el momento de esta publicación (noviembre de 2019), GitHub ofrece una versión beta de las aplicaciones de iOS y Android. Lo he estado usando durante unos días en mi iPhone X y mi iPad Mini y mi primera impresión de la aplicación es muy positiva. Se ve pulido y le brinda las características principales que esperaría en una aplicación móvil.</p><p><em>También publicado en mi blog. Si te gusta este contenido, sígueme en Twitter y GitHub.</em></p><p>Traducido del artículo de <a href="https://www.freecodecamp.org/news/author/leonardo/"><strong>Leonardo Faria</strong></a> - <strong><a href="https://www.freecodecamp.org/news/my-list-of-github-tips-and-third-party-apps/">My list of GitHub tips and third-party apps that help me stay productive</a></strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Curso de JavaScript de función de flecha – ¿Cómo Declarar una Función JS con la Nueva Sintaxis ES6? ]]>
                </title>
                <description>
                    <![CDATA[ Probablemente hayas visto funciones de flecha escritas de varias formas distintas. //ejemplo 1 const sumaDos = (num) => {return num + 2;}; //ejemplo 2 const sumaDos = (num) => num + 2; //ejemplo 3 const sumaDos = num => num + 2;   //ejemplo 4 const sumaDos = a ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/curso-de-javascript-de-funcion-de-flecha/</link>
                <guid isPermaLink="false">5ff0f7398c7cd154bb983420</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Thu, 18 Feb 2021 05:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/04/photo-1525011268546-bf3f9b007f6a.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Probablemente hayas visto funciones de flecha escritas de varias formas distintas.</p><pre><code class="language-js">//ejemplo 1
const sumaDos = (num) =&gt; {return num + 2;};

//ejemplo 2
const sumaDos = (num) =&gt; num + 2;

//ejemplo 3
const sumaDos = num =&gt; num + 2;
 
//ejemplo 4
const sumaDos = a =&gt; {
 const valorNuevo = a + 2;
 return valorNuevo;
};
</code></pre><p>Algunas tienen paréntesis alrededor de los parámetros mientras que otras no. &nbsp;Algunas utilizan corchetes y la palabra clave <code>return</code>, otras no. Una incluso se extiende en múltiples líneas mientras que las otras consisten en una línea simple.</p><p>Curiosamente, cuando invocamos las funciones de flecha de arriba con el mismo argumento, obtenemos el mismo resultado.</p><pre><code class="language-js">console.log(sumaDos(2));
//Resultado: 4
</code></pre><p>¿Cómo sabes cuál sintaxis de función de flecha usar? Eso es lo que cubrirá este artículo: cómo declarar funciones de flecha.</p><h2 id="una-gran-diferencia"><strong>Una Gran Diferencia</strong></h2><p>Las funciones de flecha son otra forma – más concisa – de escribir expresiones de funciones. Sin embargo, ellas no tienen su propio enlazamiento con la palabra clave <code><strong><strong>this</strong></strong></code>.</p><pre><code class="language-js">//Expresión de Función
const sumaNumeros = function(numero1, numero2) {
   return numero1 + numero2;
};

//Expresión de Función de Flecha
const sumaNumeros = (numero1, numero2) =&gt; numero1 + numero2;
</code></pre><p>Cuando invocamos estas funciones con los mismos argumentos obtenemos el mismo resultado.</p><pre><code class="language-js">console.log(sumaNumeros(1, 2));
//Resultado: 3
</code></pre><p>Hay una diferencia sintáctica muy importante para tener en cuenta: las funciones de flecha utilizan la flecha <strong><strong><code>=&gt;</code></strong></strong> en lugar de la palabra clave <strong><strong><code>function</code></strong></strong>. Existen otras diferencias para tener presentes cuando componemos funciones de flechas y eso es lo que vamos a explorar a continuación.</p><h2 id="par-ntesis"><strong>Paréntesis</strong></h2><p>Algunas funciones de flecha tienen paréntesis alrededor de los parámetros y otras no.</p><pre><code class="language-js">//Ejemplo con paréntesis
const sumaNumeros = (num1, num2) =&gt; num1 + num2;

//Ejemplo sin paréntesis
const sumaDos = num =&gt; num + 2;
</code></pre><p>Resulta que el número de parámetros que tiene una función de flecha determina si necesitamos incluir paréntesis o no.</p><p>Una función de flecha con <em><strong>cero parámetros</strong></em> requiere paréntesis.</p><pre><code class="language-js">const hola = () =&gt; "hola";
console.log(hola());
//Resultado: "hola"
</code></pre><p>Una función de flecha con <em><strong>un parámetro</strong></em> <em>no</em> requiere paréntesis. En otras palabras, los paréntesis son opcionales.</p><pre><code class="language-js">const sumaDos = num =&gt; num + 2;
</code></pre><p>Podemos agregar paréntesis al ejemplo de arriba y la función de flecha todavía funciona.</p><pre><code class="language-js">const sumaDos = (num) =&gt; num + 2;
console.log(sumaDos(2));
//Resultado: 4
</code></pre><p>Una función de flecha con <em><strong>múltiples parámetros</strong></em> requiere paréntesis.</p><pre><code class="language-js">const sumaNumeros = (num1, num2) =&gt; num1 + num2;
console.log(sumaNumeros(1, 2));
//Resultado: 3
</code></pre><p>Las funciones de flechas también permiten los <strong>parámetros rest</strong> y la <strong>desestructuración</strong>. Ambas características requieren paréntesis.</p><p>Este es un ejemplo de una función de flecha con el <strong>parámetro rest</strong>.</p><pre><code class="language-js">const nums = (primero, ...resto) =&gt; resto;
console.log(nums(1, 2, 3, 4));
//Resultado: [ 2, 3, 4 ]
</code></pre><p>Aquí hay una que utiliza <strong>desestructuración</strong>.</p><pre><code class="language-js">const ubicación = {
   país: "Greece",
   ciudad: "Athens"
};

const viaje = ({ciudad}) =&gt; ciudad;

console.log(viaje(ubicación));
//Resultado: "Athens"
</code></pre><p>Para resumir: si solo hay un parámetro —y no estás usando los parámetros rest o desestructuración —entonces los paréntesis son opcionales. De lo contrario, asegúrate de incluirlos.</p><h2 id="el-cuerpo-de-la-funci-n"><strong>El Cuerpo de la Función</strong></h2><p>Ahora que tenemos las reglas de los paréntesis cubiertas, nos enfoquemos en el cuerpo de la función de una función de flecha.</p><p>Un cuerpo de función de flecha puede tener <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Funciones/Arrow_functions#Cuerpo_de_funci%C3%B3n">"cuerpo conciso" o "cuerpo en bloque"</a>. &nbsp;El tipo de cuerpo influye en la sintaxis.</p><p>Primero, la sintaxis de “cuerpo conciso”.</p><pre><code class="language-js">const sumaDos = a =&gt; a + 2;
</code></pre><p>La sintaxis de “cuerpo conciso” es justamente eso: ¡es conciso! No usamos la palabra clave <code>return</code><strong><strong> </strong></strong>o corchetes.</p><p>Si tienes una función de flecha de una línea (como la del ejemplo de arriba), entonces el valor es devuelto implícitamente. Por lo tanto puedes omitir la palabra clave <code>return</code><strong><strong> </strong></strong>y los corchetes.</p><p>Ahora veamos la sintaxis de “cuerpo en bloque”.</p><pre><code class="language-js">const sumaDos = a =&gt; {
    const total = a + 2;
    return total;
}
</code></pre><p>Fíjate que utilizamos <em>ambos</em>, los corchetes y la palabra clave<strong><strong> </strong></strong><code><strong><strong>return</strong></strong></code><strong><strong> </strong></strong>en el ejemplo de arriba.</p><p>Normalmente vemos esta sintaxis cuando el cuerpo de la función tiene más de una línea. Esto es un punto clave: envolver el cuerpo de la función de flecha de varias líneas entre corchetes y usar la palabra clave <code>return</code>.</p><h3 id="objetos-y-funciones-de-flecha"><strong>Objetos y Funciones de Flecha</strong></h3><p>Existe un matiz de sintaxis más para conocer: envolver el cuerpo de la función en paréntesis cuando quieres <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Funciones/Arrow_functions#Devolver_objetos_literales">devolver objetos literales</a>.</p><pre><code class="language-js">const f = () =&gt; ({
 ciudad:"Boston"
})
console.log(f().ciudad)
</code></pre><p>Sin los paréntesis, nos da un error.</p><pre><code class="language-js">const f = () =&gt; {
   ciudad:"Boston"
}
//Resultado: error
</code></pre><p>Si encuentra la sintaxis de la función de flecha un poco confusa, no está solo. Lleva algo de tiempo familiarizarse con ello. Pero conocer sus opciones y requisitos son pasos en esa dirección.</p><p><em>Escribo sobre aprender a programar y las mejores formas de hacerlo</em> (<a href="https://amymhaddad.com">amymhaddad.com</a>).</p><p>Traducido del artículo de <strong><a href="https://www.freecodecamp.org/news/author/amy/"><strong>Amy Haddad</strong></a></strong> - <strong><a href="https://www.freecodecamp.org/news/arrow-function-javascript-tutorial-how-to-declare-a-js-function-with-the-new-es6-syntax/">Arrow Function JavaScript Tutorial – How to Declare a JS Function with the New ES6 Syntax</a></strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Git vs GitHub – ¿Qué es el Control de Versiones y Cómo Funciona? ]]>
                </title>
                <description>
                    <![CDATA[ ¿Estuviste alguna vez confundido por cómo funcionan Git y GitHub? No te preocupes – no estás solo. Git y GitHub pueden ser difícil a veces, pero al terminar este artículo tendrás una buena comprensión de ambos. Al comienzo puede ser tentador pensar que Git y GitHub son lo mismo. Pero ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/git-vs-github-what-is-version-control-and-how-does-it-work/</link>
                <guid isPermaLink="false">5fda73fe8c7cd154bb978050</guid>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ezequiel Castellanos ]]>
                </dc:creator>
                <pubDate>Sun, 14 Feb 2021 04:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/02/photo-1585770900605-fdd4161f9469-1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>¿Estuviste alguna vez confundido por cómo funcionan Git y GitHub? No te preocupes – no estás solo. Git y GitHub pueden ser difícil a veces, pero al terminar este artículo tendrás una buena comprensión de ambos.</p><p>Al comienzo puede ser tentador pensar que Git y GitHub son lo mismo. Pero en realidad no lo son. En realidad es posible utilizar Git sin GitHub! En definitiva, los dos existen por diferentes razones.</p><p>Este artículo comenzará dando una buena mirada a los propósitos de Git y GitHub. Después, vamos a aprender sobre las principales diferencias entre estas dos tecnologías vitales.</p><p>Sin más preámbulos, comencemos con Git.</p><h2 id="-qu-es-git"><strong>¿Qué es Git?</strong></h2><p>Git es un Sistema de Control de Versiones Distribuido (DVCS) utilizado para guardar diferentes versiones de un archivo (o conjunto de archivos) para que cualquier versión sea recuperable cuando lo desee.</p><p>Git también facilita el registro y comparación de diferentes versiones de un archivo. Esto significa que los detalles sobre qué cambió, quién cambió qué, o quién ha iniciado una propuesta, se pueden revisar en cualquier momento.</p><p>¿Pero si Git es un Sistema de Control de Versiones Distribuido, qué significan exactamente esos términos?</p><h3 id="-qu-significa-distribuido"><strong>¿Qué significa "distribuido"?</strong></h3><p>El término "distribuido" significa que cuando le instruyes a Git que comparta el directorio de un proyecto, Git no sólo comparte la última versión del archivo. En cambio, distribuye cada versión que ha registrado para ese proyecto.</p><p>Este sistema "distribuido" tiene un marcado contraste con otros sistemas de control de versiones. Ellos sólo comparten cualquier versión individual que un usuario haya explícitamente extraído desde la base de datos central/local.</p><p>Bueno, entonces "distribuido" significa distribuir <em>todas – </em>no solo algunas seleccionadas – versiones de los archivos del proyecto que Git haya registrado. Pero qué es exactamente un sistema de control de versiones?</p><h3 id="-qu-es-un-sistema-de-control-de-versiones"><strong>¿Qué es un Sistema de Control de Versiones?</strong></h3><p>Un Sistema de Control de Versiones (VCS) se refiere a<em>l método</em> utilizado para guardar las versiones de un archivo para referencia futura.</p><p>De manera intuitiva muchas personas ya utilizan control de versiones en sus proyectos al renombrar las distintas versiones de un mismo archivo de varias formas como <code>blogScript.js</code>, <code>blogScript_v2.js</code>, <code>blogScript_v3.js</code>, <code>blogScript_final.js</code>, <code>blogScript_definite_final.js</code>, etcétera. Pero esta forma de abordarlo es propenso a errores y inefectivo para proyectos grupales.</p><p>Además, con esta forma de abordarlo, rastrear qué cambió, quién lo cambió y porqué se cambió, es un esfuerzo tedioso. Esto resalta la importancia de un sistema de control de versiones confiable y colaborativo como Git.</p><p>Sin embargo, para obtener lo mejor de Git, es importante entender cómo Git administra tus archivos.</p><h2 id="estados-de-los-archivos-en-git"><strong>Estados de los archivos en Git</strong></h2><p>En Git hay tres etapas primarias (condiciones) en las cuales un archivo puede estar: <strong>estado modificado</strong>, <strong>estado preparado</strong>, o <strong>estado confirmado</strong>.</p><h3 id="estado-modificado"><strong>Estado modificado</strong></h3><p>Un archivo en el estado modificado es un archivo revisado – pero no acometido (sin registrar).</p><p>En otras palabras, archivos en el estado modificado son archivos que has modificado pero no le has instruido explícitamente a Git que controle.</p><h3 id="estado-preparado"><strong>Estado preparado</strong></h3><p>Archivos en la etapa preparado son archivos modificados que han sido seleccionados – en su estado (versión) actual – y están siendo preparados para ser guardados (acometidos) al repositorio <code>.git</code> durante la próxima instantánea de confirmación.</p><p>Una vez que el archivo está preparado implica que has explícitamente autorizado a Git que controle la versión de ese archivo.</p><h3 id="estado-confirmado"><strong>Estado confirmado</strong></h3><p>Archivos en el estado confirmado son archivos que se guardaron en el repositorio <code>.git</code> exitosamente.</p><p>Por lo tanto un archivo confirmado es un archivo en el cual has registrado su versión preparada en el directorio (carpeta) Git.</p><p><strong><strong>Not</strong>a<strong>: </strong></strong>El estado de un archivo determina la ubicación donde Git lo colocará.</p><h2 id="ubicaci-n-de-archivos"><strong>Ubicación de archivos</strong></h2><p>Existen tres lugares principales donde pueden residir las versiones de un archivo cuando se hace control de versiones con Git: el <strong>directorio de trabajo</strong>, el <strong>sector de preparación</strong>, o el <strong>directorio Git</strong>. </p><h3 id="directorio-de-trabajo"><strong>Directorio de trabajo</strong></h3><p>El directorio de trabajo es una carpeta local para los archivos de un proyecto. Esto significa que cualquier carpeta creada en cualquier lugar en un sistema es un directorio de trabajo.</p><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>Los archivos en el estado modificado residen dentro del directorio de trabajo.</li><li>El directorio de trabajo es distinto al directorio <code>.git</code>. Es decir, tu creas un directorio de trabajo mientras que Git crea un directorio <code>.git</code>.</li></ul><h3 id="zona-de-preparaci-n"><strong>Zona de preparación</strong></h3><p>La zona de preparación – técnicamente llamado “index” en lenguaje Git &nbsp;– es un archivo normalmente ubicado en el directory <code>.git</code>, que guarda información sobre archivos próximos a ser acometidos en el directorio <code>.git</code>.</p><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>Los archivos en la etapa de preparación residen en la zona de preparación.</li></ul><h3 id="directorio-git"><strong>Directorio Git</strong></h3><p>El directorio<code>.git</code> es la carpeta (también llamada "repositorio") que Git crea dentro del directorio de trabajo que le has instruido para realizar un seguimiento.</p><p>La carpeta <code>.git</code> también es donde Git guarda las bases de datos de objetos y metadatos de los archivos que le hayas instruido realizar un monitoreo.</p><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>El directorio<code>.git</code> es la vida de Git – es el item copiado cuando se clona un repositorio desde otra computadora (o desde una plataforma en línea como GitHub).</li><li>Los archivos en el estado acometido residen en el directorio Git.</li></ul><h2 id="el-flujo-de-trabajo-b-sico-de-git">El flujo de trabajo básico de Git</h2><p>Trabajar con el Sistema de Control de Versiones Git se ve algo así:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2020/08/git-basic-workflow-codesweetly.png" class="kg-image" alt="Diagrama básico del flujo de trabajo de Git" width="600" height="400" loading="lazy"></figure><ol><li>Modificar archivos en el directorio de trabajo.<br>Observe que cualquier archivo que modifiques se convierte en un archivo en el <em>estado modificado</em>.</li><li>Prepare selectivamente los archivos que quieras confirmar al directorio <code>.git</code>.<br>Observe que cualquier archivo que prepares (agregues) a la zona de preparación se convierte en un archivo en el <em>estado preparado</em>. &nbsp; <br>También tenga en cuenta que los archivos preparados todavía no están en la base de datos <code>.git</code>.<br>Preparar significa que la información sobre el archivo preparado se incluye en un archivo (llamado "index") en el repositorio <code>.git</code>.</li><li>Confirme el/los archivos que has preparado en el directorio <code>.git</code>. Esto es, guardar de manera permanente una instantánea de los archivos preparados en la base de datos <code>.git</code>.<br>Observe que cualquier versión del archivo que confirmes al directorio <code>.git</code> se convierte en un archivo en el <em>estado confirmado</em>.</li></ol><h3 id="lo-esencial-hasta-ahora"><strong>Lo esencial hasta ahora</strong></h3><p>En resumidas cuentas de todo lo discutido hasta el momento es que Git es un sistema de control de versiones genial para versionado, administración y distribución de archivos.</p><p>Pero espera un segundo, si Git nos ayuda en la administración y distribución eficaz de distintas versiones de los archivos de un proyecto, &nbsp;¿cúal es el propósito de GitHub?</p><h2 id="github-desmitificado"><strong>GitHub </strong>Desmitificado</h2><p>GitHub es una plataforma basada en la web donde los usuarios pueden alojar repositorios Git. Facilita compartir y colaborar fácilmente en proyectos con cualquier persona en cualquier momento.</p><p>GitHub también fomenta una participación más amplia en proyectos Código Abierto al proporcionar una manera segura de editar archivos en repositorios de otros usuarios.</p><p>Para alojar (o compartir) un repositorio Git en GigHub, siga los siguientes pasos:</p><h3 id="paso-1-registrar-una-cuenta-de-github"><strong>Paso 1: Registrar una cuenta de GitHub</strong></h3><p>El primer paso para comenzar con el alojamiento en GitHub es crear una cuenta personal. Visite la <a href="https://github.com/join">página de registro oficial</a> para registrarse.</p><h3 id="paso-2-crear-un-repositorio-remoto-en-github"><strong>Paso 2: Crear un repositorio remoto en GitHub</strong></h3><p>Después de registrarse, <a href="https://docs.github.com/es/free-pro-team@latest/github/getting-started-with-github/create-a-repo">crear un home (un repositorio) en GitHub</a> para el repositorio Git que quieres compartir. </p><h3 id="paso-3-conectar-el-directorio-git-del-proyecto-con-el-repositorio-remoto"><strong>Paso 3: Conectar el directorio Git del proyecto con el repositorio remoto</strong></h3><p>Una vez que hayas creado un repositorio remoto para tu proyecto, tienes que vincular el directorio <code>.git</code> del proyecto – ubicado localmente en tu sistema – con el repositorio remoto en GitHub.</p><p>Para conectar con el repositorio remoto, debes <strong>ubicarte en el directorio raíz</strong> del proyecto que quieras compartir, utilizando tu terminal local, y ejecuta este comando:</p><pre><code>git remote add origin https://github.com/tuUsuario/tuRepositorio.git</code></pre><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>Reemplaza <code>tuUsuario</code> en el código de arriba con tu nombre de usuario de GitHub.<br>También reemplaza <code>tuRepositorio</code> con el nombre del repositorio remoto al que te quieres conectar.</li><li>El comando de arriba implica que <em><em>git</em></em> debe <em><em>a</em>gregar</em> al proyecto la <em>URL </em>especificada como una referencia remota con la cual el directorio local <code>.git</code> puede interactuar.</li><li>La opción <code>origin</code> en el comando de arriba es el nombre predeterminado (un nombre corto) que Git le otorga al servidor que aloja tu repositorio remoto.<br>Es decir, Git utiliza el nombre corto <code>origin</code> en vez de la URL del servidor.</li><li>No es obligatorio quedarse con el nombre predeterminado del servidor. Si prefieres otro nombre que <code>origin</code>, simplemente sustituya el nombre <code>origin</code> en el comando <code>git remote add</code> de arriba por cualquier nombre que prefieras.</li><li>Siempre recuerda que un nombre corto del servidor (por ejemplo, &nbsp;<code>origin</code>) no es nada especial! Sólo existe – localmente – para ayudarte a referenciar fácilmente la URL del servidor. Por lo tanto, siéntete libre de cambiarlo a un nombre corto que puedas referenciar fácilmente.</li><li>Para renombrar cualquier URL remota que exista, utilice el comando <code>git remote rename</code> de esta manera:</li></ul><pre><code>git remote rename nombreURLactual nuevoNombreURL</code></pre><ul><li>Cada vez que clones (descargues) cualquier repo remota, Git automáticamente le pone nombre <code>origin</code> a la URL de la repo. Sin embargo, le puedes especificar un nombre distinto con el comando <code>git clone -o tuNombrePreferido</code>.</li><li>Para ver la URL exacta guardada para los nombres como <code>origin</code>, ejecuta el comando <code>git remote -v</code>.</li></ul><h3 id="paso-4-confirmar-la-conexi-n"><strong>Paso 4: Confirmar la conexión</strong></h3><p>Una vez que hayas conectado tu directorio Git con el repositorio remoto, verifica si la conexión fue exitosa ejecutando el comando <code>git remote -v</code>.</p><p>Después verifica la impresión para confirmar que la <em>URL mostrada</em> sea la misma que la <em>URL remota</em> que intentas conectarte.</p><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>Ver el artículo “<a href="https://docs.github.com/es/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh">Conectar con SSH</a>” si quieres conectar utilizando la URL SSH en lugar de la URL HTTPS.</li><li>Sin embargo, si no estás seguro de la URL remota que vas a utilizar, echa un vistazo al artículo “<a href="https://docs.github.com/es/free-pro-team@latest/github/using-git/which-remote-url-should-i-use">¿Qué URL remota debería utilizar?</a>”.</li><li>¿Quieres cambiar tu URL remota? <a href="https://docs.github.com/es/free-pro-team@latest/github/using-git/changing-a-remotes-url">Cambiar la URL de un remoto</a> es una excelente guía.</li></ul><h3 id="paso-5-subir-un-repo-git-local-a-un-repo-remoto"><strong>Paso 5: Subir un repo Git local a un repo remoto</strong></h3><p>Después de conectar exitosamente tu directorio local con el repositorio remoto puedes comenzar a subir (cargar) tu proyecto local upstream.</p><p>Cuando estés listo para compartir tu proyecto en otra parte, en cualquier repo remoto, simplemente le dices a Git que suba todos tus confirmaciones, ramas y archivos en tu directorio <code>.git</code> local al repositorio remoto.</p><p>La sintaxis del código utilizado para subir (push) un directorio local Git a un repositorio remoto es <code>git push -u nombreRemoto nombreRama</code>.</p><p>Esto es, para subir tu directorio local <code>.git</code> y suponiendo que el nombre corto de la URL remota es “origin”, ejecuta:</p><pre><code>git push -u origin master</code></pre><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>El comando de arriba implica que <em>git </em>debe <em>subir </em>tu rama <em>master </em>local a la rama <em>master </em>remota ubicada en la URL con nombre <em>origin</em>.</li><li>Técnicamente puedes sustituir la opción <code>origin</code> con la URL del repositorio remoto. Recuerda, la opción <code>origin</code> es solo un nombre de la URL que hayas registrado en tu directorio <code>.git</code> local.</li><li>El indicador <code>-u</code> (indicador de referencia upstream/seguimiento) automáticamente vincula la rama local del directorio <code>.git</code> con la rama remota. Esto te permite usar <code>git pull</code> sin ningún argumento.</li></ul><h3 id="paso-6-confirmar-la-subida"><strong>Paso 6: Confirmar la subida</strong></h3><p>Por último, vuelve a tu página de repositorio GitHub para confirmar que Git haya subido exitosamente tu directorio Git local al repositorio remoto.</p><p><strong><strong>Not</strong>a<strong>:</strong></strong></p><ul><li>Tal vez tengas que refrescar la página del repositorio remoto para reflejar los cambios.</li><li>GitHub también tiene un servicio gratuito opcional para convertir tu repositorio remoto en una página web funcional. Abajo vamos a ver “cómo” hacerlo.-</li></ul><h2 id="publica-tu-p-gina-web-con-github-pages"><strong>Publica tu página web con GitHub pages</strong></h2><p>Después de subir tu proyecto al repositorio remoto, fácilmente puedes publicarlo en la web de esta forma:</p><ol><li>Asegurate que el nombre del archivo principal HTML de tu proyecto sea <code>index.html</code>.</li><li>En el sitio web de la plataforma GitHub ingresa al repositorio del proyecto que quieres publicar y haz click en la <strong>pestaña settings</strong>.</li><li>Desplaza hacia la sección <strong><strong>GitHub Pages</strong></strong> y cambia la rama <strong><strong>Source</strong></strong> de <strong><strong>none</strong></strong> a <strong><strong>master</strong></strong>.</li><li>Después aparecerá una notificación que dice “Your site is published at <em><em>https://your-username.github.io/your-github-repo-name/</em></em>”.</li><li>Ahora puedes ver – y publicitar – tu proyecto en la URL especificada.</li></ol><p>Esta sección solo ha comenzado a tratar el tema de publicar tu proyecto con GitHub. Para aprender más sobre GitHub pages, echa un vistazo a esta documentación “<a href="https://docs.github.com/es/free-pro-team@latest/github/working-with-github-pages">Trabajar con páginas de GitHub Pages</a>”.</p><h3 id="en-resumen"><strong>En resumen</strong></h3><p>GitHub es una plataforma en línea de alojamiento (o para compartir) repositorios de Git. Nos ayuda crear una avenida para colaborar fácilmente con cualquier persona, en cualquier lugar, en cualquier momento.</p><h2 id="todav-a-en-duda"><strong>Todavía en duda?</strong></h2><p>Todavía estás perplejo por la delgada línea entre Git y GitHub? No te preocupes – Te tengo cubierto. Abajo hay cinco diferencias claves entre Git y GitHub.</p><h3 id="diferencia-1-git-vs-github-funci-n-principal"><strong>Diferencia 1: Git vs. GitHub — Función principal</strong></h3><p><strong><strong>Git</strong></strong> es un sistema de control de versiones distribuido que registra las distintas versiones de un archivo (o conjunto de archivos). Le permite a los usuarios acceder, comparar, actualizar, y distribuir cualquiera de las versiones registradas en cualquier momento.</p><p>Sin embargo <strong><strong>GitHub</strong></strong> principalmente es una plataforma de alojamiento para albergar tus repositorios Git en la web. Esto permite a los usuarios mantener sus repositorios remotos privados o abiertos para esfuerzos colaborativos.</p><h3 id="diferencia-2-git-vs-github-plataforma-de-operaci-n"><strong>Diferencia 2: Git vs. GitHub — Plataforma de operación</strong></h3><p>Los usuarios instalan y ejecutan Git en sus equipos locales. Esto significa que la mayoría de las operaciones de Git se pueden lograr sin una conexión a internet.</p><p>Sin embarg GitHub es un servicio basado en la web que opera solamente en línea. Esto significa que necesitas estar conectado para hacer cualquier cosa en GitHub.</p><h3 id="diferencia-3-git-vs-github-creadores"><strong>Diferencia 3: Git vs. GitHub — Creadores</strong></h3><p>Linus Torvalds comenzó Git en Abril del 2005.</p><p>Chris Wanstrath, P. J. Hyett, Tom Preston-Werner, y Scott Chacon fundaron GitHub.com en Febrero 2008.</p><h3 id="diferencia-4-git-vs-github-mantenedores"><strong>Diferencia 4: Git vs. GitHub — Mantenedores</strong></h3><p>En Julio 2005, Linus Torvalds entregó el mantenimiento de Git a Junio C. Hamano — quien ha sido el principal mantenedor desde entonces.</p><p>En Octubre 2018, Microsoft compró GitHub.</p><h3 id="diferencia-5-git-vs-github-competidores"><strong>Diferencia 5: Git vs. GitHub — Competidores</strong></h3><p>Algunas alternativas populares para Git son Mercurial, Team Foundation Version Control (TFVC), Perforce Helix Core, Apache Subversion, y IBM Rational ClearCase.</p><p>Los competidores más cercanos a GitHub son GitLab, Bitbucket, SourceForge, Cloud Source Repositories, y AWS CodeCommit.</p><h2 id="considerando-todo"><strong>Considerando todo</strong></h2><p>Git y GitHub son dos entidades diferentes que te ayudan a administrar y alojar archivos. En otras palabras Git sirve para controlar las versiones de los archivos mientras que GitHub es una plataforma para alojar tus repositorios Git.</p><p>Traducido del artículo -<strong> </strong><a href="https://www.freecodecamp.org/news/git-and-github-overview/">Git vs GitHub – What is Version Control and How Does it Work?</a> de <a href="https://www.freecodecamp.org/news/author/oluwatobi/"><strong>Oluwatobi Sofela</strong></a></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
