<?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[ Lucas Agustín Morales Romero - 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[ Lucas Agustín Morales Romero - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 12 Jun 2026 04:57:52 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/lucas-agustin-morales-romero/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Como construir una app de chat en tiempo real con ReactJS y Firebase ]]>
                </title>
                <description>
                    <![CDATA[ En este artículo, voy a mostrarte como crear una app de chat en tiempo real usando React.js y Firebase. En la app, vamos a permitir que los usuarios se logueen con su cuenta de Google usando el servicio de inicio de sesion de Firebase. También guardaremos y recuperaremos todos los ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-construir-una-app-de-chat-en-tiempo-real-con-reactjs-y-firebase/</link>
                <guid isPermaLink="false">6638d45a29a7ee03fce3bb36</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lucas Agustín Morales Romero ]]>
                </dc:creator>
                <pubDate>Tue, 15 Apr 2025 14:56:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2024/05/Cover-Images-freeCodeCamp.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/building-a-real-time-chat-app-with-reactjs-and-firebase/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Build a Real-time Chat App with ReactJS and Firebase</a>
      </p><p>En este artículo, voy a mostrarte como crear una app de chat en tiempo real usando React.js y Firebase.</p><p>En la app, vamos a permitir que los usuarios se logueen con su cuenta de Google usando el servicio de inicio de sesion de Firebase. También guardaremos y recuperaremos todos los mensajes usando el servicio Firestone de Firebase. </p><h2 id="prerrequisitos"><strong>Prerrequisitos</strong></h2><p>Para este tutorial, deberás tener instalado Node.js en tu sistema, además deberás tener conocimientos intermedios de CSS, JavaScript y ReactJS y conocimientos sobre el uso de la terminal de líneas de comandos. No debes saber utilizar Firebase para hacer el mismo.</p><h2 id="-que-es-firebase"><strong>¿Que es Firebase?</strong></h2><p>Firebase es un <a href="https://es.wikipedia.org/wiki/Backend_as_a_service">BaaS (Backend as a Service)</a>, una plataforma de backend propiedad de Google que permite a desarrolladores construir aplicaciones para iOS, Android o aplicaciones web.</p><p>Nos provee con herramientas para el seguimiento de análisis, reportar y solucionar fallas de aplicaciones y crear pruebas de marketing y productos. Esto, ayuda a los desarrolladores a crear aplicaciones de calidad, hacer crecer su base de usuarios y obtener ganancias.</p><p>Para este tutorial, vamos a utilizar dos herramientas: Firebase Authentication y Cloud Firestone.</p><h3 id="firebase-authentication"><strong><strong><strong>Firebase Authentication</strong></strong></strong></h3><p>Firebase Authentication (SDK) es una herramienta de Firebase que permite realizar autenticación de usuarios mediante varios métodos, como contraseñas, números de telefono, cuentas de Google, Facebook, Twitter, GitHub y mas. En este proyecto usaremos la autenticación a través de cuentas de Google.</p><h3 id="cloud-firestore"><strong><strong><strong>Cloud Firestore</strong></strong></strong></h3><p>Cloud Firestones es un servicio de bases de datos no relacionales que nos permite guardar y sincronizar información. Este servicio guarda la información en documentos como pares de clave-valor, y estos documentos en colecciones.</p><p>Los documentos, a su vez pueden tener sub-colecciones, permitiéndonos anidar colecciones dentro de otras colecciones, además la información se sincroniza automáticamente entre todos los dispositivos que estén consultando esos datos.</p><p>Ahora que ya tienes una idea general de como trabajan Firebase y Cloud Firestone, vamos a trabajar en el proyecto.</p><p><strong><strong>Not</strong>a<strong>:</strong></strong> para este proyecto, ya escribí el CSS y preconstruí los componentes para la aplicación de chat, puedes encontrar el código del proyecto final en <a href="https://github.com/Timonwa/react-chat">GitHub</a> y los componentes junto con el CSS en la carpeta <a href="https://github.com/Timonwa/react-chat/tree/main/setup">"setup"</a>, y también puedes ver el proyecto final funcionando en este <a href="https://react-chat-timonwa.vercel.app/">link</a></p><h2 id="como-crear-nuestra-aplicaci-n-de-react"><strong>Como crear nuestra aplicación de React</strong></h2><p>Clona este repositorio de <a href="https://github.com/Timonwa/react-chat">GitHub</a>, borra la carpeta src en el directorio raíz y remplázala con la carpeta "src" que se encuentra en la carpeta <a href="https://github.com/Timonwa/react-chat/tree/main/setup">"setup"</a>.</p><p>Alternativamente, puedes crear tu aplicación de React corriendo el comando create-react-app en la terminal.</p><pre><code class="language-node">npx create-react-app react-chat</code></pre><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/06/install-create-react-app.jpg" class="kg-image" alt="install-create-react-app" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/06/install-create-react-app.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/2024/06/install-create-react-app.jpg 776w" width="776" height="430" loading="lazy"><figcaption>Comando create-react-app corriendo (en la parte superior se ve el comando de instalación: npm install -g create-react.app)</figcaption></figure><p><code>react-chat</code> &nbsp;es el nombre de la aplicación. Una vez que finaliza correremos el comando &nbsp;<code>npm install firebase react-firebase-hooks</code> para instalar <strong><strong>firebase</strong></strong> y <strong><strong>react-firebase-hooks</strong></strong>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/06/install-firebase.jpg" class="kg-image" alt="install-firebase" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/06/install-firebase.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/2024/06/install-firebase.jpg 770w" width="770" height="267" loading="lazy"><figcaption>Comando install firebase react-firebase-hooks corriendo (se aprecia que primeramente se cambio al directorio react-chat</figcaption></figure><p>Una vez que finaliza, borra la carpeta <strong><strong>src</strong></strong> y reemplazala con la que descargaste de la <a href="https://github.com/Timonwa/react-chat/tree/main/setup">carpeta setup</a> para usar el archivo CSS y los componentes preconstruidos. (Opcionalmente, puedes escribir tus propios componentes y tu propio archivo CSS)</p><p>Ahora, tu carpeta <strong><strong>src</strong></strong> contiene los siguientes componentes:</p><ul><li>Una carpeta de componentes con un componente <strong><strong>NavBar</strong></strong> que contiene los botones de <strong><strong>Google sign-in</strong></strong> y <strong><strong>Sign Out</strong>,</strong></li><li>Un componente que le da la <strong>Bienvenida</strong> al usuario que no está logueado,</li><li>Un componente <strong><strong>Chatbox</strong></strong> que solo es visible cuando el usuario está logueado.</li><li>El componente <strong><strong>Message</strong></strong> para mostrar los mensajes de los usuarios,y</li><li>El componente <strong><strong>SendMessage</strong></strong> que usaremos para que el usuario pueda escribir y enviar sus mensajes.</li></ul><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/componentes-en-vs-code.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667917866994_image2.png" width="146" height="217" loading="lazy"></figure><p>Además, tenemos lo siguiente:</p><ul><li>Una carpeta <strong><strong>img</strong></strong> donde se guarda la imagen de Google sign-in y sign-out,</li><li>un archivo CSS llamado <strong><strong>App.css</strong></strong> con el código CSS para la aplicación,</li><li>un archivo llamado <strong><strong>App.js</strong></strong> con todos los componentes importados dentro,</li><li>y un archivo llamado <strong><strong>index.js</strong></strong>.</li></ul><p>Corre el comando <code>npm start</code> para ver la aplicación en el navegador, deberías ver algo como esto:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/react-chat-running.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667916861885_image1.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/react-chat-running.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/react-chat-running.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/react-chat-running.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/react-chat-running.jpg 1916w" sizes="(min-width: 1200px) 1200px" width="1916" height="920" loading="lazy"><figcaption>Nuestra app de React corriendo en Local</figcaption></figure><p>Ahora, creemos una cuenta de Firebase y configuremos nuestro proyecto.</p><h2 id="como-configurar-el-proyecto-en-firebase"><strong>Como configurar el proyecto en Firebase</strong></h2><p>Si todavía no tienes una cuenta de <a href="https://firebase.google.com/">Firebase</a>, puedes abrir una usando tu correo de Gmail (solo se puede usar el <a href="https://mail.google.com/mail">mail de Google</a>). </p><p>En la página de inicio, haga clic en <strong>comenzar </strong>y luego en crear un proyecto.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-web.jpg" class="kg-image" alt="firebase-web" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-web.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-web.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-web.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-web.jpg 1903w" sizes="(min-width: 1200px) 1200px" width="1903" height="924" loading="lazy"></figure><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-web-crear.jpg" class="kg-image" alt="firebase-web-crear" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-web-crear.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-web-crear.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-web-crear.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-web-crear.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="918" loading="lazy"></figure><p>Completa el formulario para crear el proyecto agregando un nombre de proyecto (en nuestro caso usaremos el nombre React-chat). Si quieres dejar habilitado Google Analytics para tu proyecto déjalo, sino deshabilítalo. Después, haz clic en crear proyecto</p><p></p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-paso1.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667930368482_image5.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-paso1.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-paso1.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-paso1.jpg 1177w" width="1177" height="739" loading="lazy"><figcaption>Creando el proyecto paso 1</figcaption></figure><p>Una vez creado, presiona el botón <strong><strong>Continu</strong>ar</strong>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-pasoFinal.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667930783189_image8.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-pasoFinal.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-pasoFinal.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-pasoFinal.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-pasoFinal.jpg 1832w" sizes="(min-width: 1200px) 1200px" width="1832" height="906" loading="lazy"><figcaption>Lo que verás mientras Firebase crea tu proyecto.</figcaption></figure><p>Elige el tipo de aplicación al que quieres agregar Firebase, para este artículo elegiremos el icono de código porque estamos desarrollando una aplicación 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/2024/07/firebase-final-1.jpg" class="kg-image" alt="firebase-final-1" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-final-1.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-final-1.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-final-1.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-final-1.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="913" loading="lazy"><figcaption>Elige el tipo de aplicación al que quieres integrar Firebase</figcaption></figure><p></p><p>Ingresa un sobrenombre para la aplicación y haz clic en el botón <strong>registrar app</strong>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-registrar-app.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667934485512_image10.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-registrar-app.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-registrar-app.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-registrar-app.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-registrar-app.jpg 1916w" sizes="(min-width: 1200px) 1200px" width="1916" height="916" loading="lazy"><figcaption>Registra tu app</figcaption></figure><p>En el menú selecciona npm, copia el código (lo vamos a utilizar más tarde) y haz clic en <strong>ir a la consola</strong>. </p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-sdk.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667934988668_image11.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-sdk.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-sdk.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-sdk.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-sdk.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="918" loading="lazy"><figcaption>Código para el SDK de Firebase</figcaption></figure><h2 id="c-mo-configurar-firebase-authentication"><strong>Cómo configurar Firebase Authentication</strong></h2><p>Para configurar Firebase Authentication, ve al menú de la izquierda y presiona sobre <strong>Compilación </strong>y selecciona <strong>Aut<strong>hentication</strong></strong> del desplegable.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-autentication.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667937032772_image12.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-autentication.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-autentication.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-autentication.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-autentication.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="918" loading="lazy"><figcaption>Selecciona Authentication del menú desplegable.</figcaption></figure><p>Haz clic en comenzar y selecciona a Google en el menú proveedores de acceso.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-autentication-conf.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667937105063_image13.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-autentication-conf.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-autentication-conf.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-autentication-conf.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-autentication-conf.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="920" loading="lazy"><figcaption>Elige el método de autenticación.</figcaption></figure><p>Presiona sobre el botón de la derecha para habilitar el proyecto y selecciona un correo de soporte, luego haz clic en guardar.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-autentication-conf-mail.jpg" class="kg-image" alt="https://paper-attachments.dropboxusercontent.com/s_B6DDEC735898D3445BBF655B53FFE42B53361DCD6229DE6836CD5302F930DF9D_1667937310260_image14.png" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-autentication-conf-mail.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-autentication-conf-mail.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-autentication-conf-mail.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-autentication-conf-mail.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="921" loading="lazy"></figure><h2 id="c-mo-configurar-cloud-firestone"><strong>Cómo configurar Cloud Firestone</strong></h2><p>Nuevamente. ve al menú de la izquierda, clickea en <strong>compilación</strong> y selecciona <strong>Firestone</strong>. Luego haz clic en crear base de datos y completa el formulario.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firestone-db.jpg" class="kg-image" alt="image9-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firestone-db.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firestone-db.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firestone-db.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firestone-db.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="921" loading="lazy"><figcaption>Configurando Cloud Firestore</figcaption></figure><p>En el primer paso, selecciona la localización de la base de datos, por defecto el sistema asignará la ubicación más cercana a la que te encuentras, luego presiona siguiente. </p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firestone-db-seteo1.jpg" class="kg-image" alt="firestone-db-seteo1" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firestone-db-seteo1.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firestone-db-seteo1.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firestone-db-seteo1.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firestone-db-seteo1.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="916" loading="lazy"><figcaption>Setea la localización de la base de datos y presiona siguiente.</figcaption></figure><p>Selecciona el modo de la base de datos, puedes elegir producción o modo de prueba.</p><p>El modo de prueba permite que cualquier cliente puede leer o escribir en la base de datos por 30 días. El modo producción significa que nadie puede leer o escribir en la base de datos, por lo que debes escribir tus reglas para brindar acceso a la base de datos.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firestone-db-seteo2.jpg" class="kg-image" alt="image10-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firestone-db-seteo2.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firestone-db-seteo2.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firestone-db-seteo2.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firestone-db-seteo2.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="920" loading="lazy"><figcaption>Elige el modo de producción o el modo de pruebas (nosotros elegiremos el modo de producción).</figcaption></figure><p>Selecciona <strong>modo de producción</strong> y presiona el botón <strong>crear</strong>.</p><p>El siguiente paso será editar nuestras reglas, haz clic en la pestaña <strong>reglas</strong>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-reglas-1.jpg" class="kg-image" alt="image12-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-reglas-1.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-reglas-1.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-reglas-1.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-reglas-1.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="899" loading="lazy"><figcaption>Edita las reglas ingresando en la pestaña Reglas.</figcaption></figure><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-reglas-2.jpg" class="kg-image" alt="image13-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/firebase-reglas-2.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/firebase-reglas-2.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2024/07/firebase-reglas-2.jpg 1600w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/firebase-reglas-2.jpg 1920w" sizes="(min-width: 1200px) 1200px" width="1920" height="918" loading="lazy"><figcaption>Reemplaza esta regla.</figcaption></figure><p>Reemplaza la regla que esta en la pestaña por la siguiente y presiona el boton <strong>publicar</strong>.</p><pre><code class="language-js">rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if true;
      allow create, update, delete, write: if request.auth != null;
    }
  }
}</code></pre><p>Analicemos el código, la primer parte, &nbsp;<code>allow read: if true;</code> significa que cualquiera puede leer tu base de datos, mientras que el bloque de código siguiente <code>allow create, update, delete, write: if request.auth != null;</code> significa que solo los clientes autenticados pueden crear, actualizar, borrar y escribir datos en la base de datos.</p><p>Puedes comenzar agregando o creando una colección en tu base de datos o crear una automáticamente en la aplicación que estamos desarrollando, lo que haremos después. Si quieres crear una colección en Cloud Firestone, vuelve a la pestaña de <strong>datos </strong>presionando en la misma y presiona el botón <strong>iniciar coleccion</strong>.</p><p>Ingresa el nombre de la colección, por ejemplo "messages" y clickea en <strong>siguiente</strong>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/coleecion-ejemplo.jpg" class="kg-image" alt="image14-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/coleecion-ejemplo.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/coleecion-ejemplo.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/coleecion-ejemplo.jpg 1099w" width="1099" height="626" loading="lazy"><figcaption>Iniciando una colección en Firestone.</figcaption></figure><p>Ahora, crea el documento para la colección, </p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/07/coleecion-ejemplo-2.jpg" class="kg-image" alt="image15-1" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/07/coleecion-ejemplo-2.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2024/07/coleecion-ejemplo-2.jpg 1000w, https://www.freecodecamp.org/espanol/news/content/images/2024/07/coleecion-ejemplo-2.jpg 1117w" width="1117" height="664" loading="lazy"><figcaption>Creando un documento para la colección.</figcaption></figure><p>Clickea en <strong>ID automático</strong>, de esa forma el sistema generará el ID de forma automática, o si lo prefieres ingresa uno tu.</p><p>Luego, se crea el par clave-&gt;valor para el documento. El campo llamado "Campo" representa el nombre de la clave, el campo "Tipo" nos dice que valor almacena (cadena de texto, number, timeStamp, etc), y finalmente el campo "Valor" es lo que guardamos en esta clave.</p><p>Puedes seguir agregando más documentos presionando en el enlace "Agregar campo", sino presiona en Guardar para que se guarde la colección.</p><p>Nuestro proyecto de Firebase ya esta correctamente seteado, volvamos a la aplicación de React.</p><h2 id="c-mo-configurar-firebase-en-react"><strong>Cómo configurar Firebase en React</strong></h2><p>En la carpeta <strong><strong>src</strong></strong>, crea un archivo llamado <code>firebase.js</code> y pega el código que copiamos al configurar firebase.</p><p>Tambien importemos los servicios <code>getAuth</code> &nbsp;y <code>getFirestore</code> desde <a href="https://firebase.google.com/docs/auth/web/start?hl=es">Autenticación para Web</a> y <a href="https://firebase.google.com/docs/firestore/quickstart?hl=es">Firestore en la nube para web</a> respectivamente. Puedes leer más sobre las bibliotecas disponibles para Firebase en la página de la <a href="https://firebase.google.com/docs/web/setup?hl=es#available-libraries">documentación</a>.</p><p>Nuestro archivo firebase.js debe verse asi:</p><pre><code class="language-js">// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: LA_CLAVE_PARA_LA_APLICACION_VA_AQUI(CLAVE_API),
  authDomain: EL_DOMINIO_DE_AUTENTICACION_PARA_LA_APP_VA_AQUI,
  projectId: EL_ID_DEL_PROYECTO_PARA_LA_APP_VA_AQUI,
  storageBucket: EL_BUCKET_PARA_LA_APLICACION_VA_AQUI,
  messagingSenderId: EL_ID_PARA_ENVIAR_LOS_MENSAJES_VA_AQUI,
  appId: EL_APP_ID_DE_LA_APLICACION_DE_REACT_VA_AQUI,
};</code></pre><h2 id="c-mo-implementar-firebase-dentro-de-nuestra-aplicaci-n-react"><strong>Cómo implementar Firebase dentro de nuestra aplicación React</strong></h2><h3 id="c-mo-autenticar-usuarios-con-su-cuenta-de-google"><strong>Cómo autenticar usuarios con su cuenta de Google</strong></h3><p>Nosotros queremos que los usuarios tengan acceso a la aplicación de chat y que en caso de que estén autenticados puedan enviar mensajes, si no lo están queremos que vean la página de bienvenida para poder loguearse usando el botón de Google sign-in, y si esta logueado debe poder ver el botón de Sign-out para salir del chat.</p><p>Esta autenticación será controlada por el componente NavBar, que contiene ambos botones (sign-in y sign-out).</p><p>En nuestro componente <code>NavBar</code>, importaremos nuestra imagen de Google "sign-in", y la guardaremos como la constante llamada <code>GoogleSignin</code>. También tendremos un estado llamado <code>user</code>, seteado como falso, una función llamada <code>googleSignIn</code> que setea el estado de <code>user</code> como verdadero, y una función llamada <code>signOut</code> que setea el estado de <code>user</code> como falso. </p><p>También tenemos un elemento <code>nav</code> con un tag <code>h1</code> que representa el título de nuestra app y dos botones que se renderizan condicionalmente en base al estado del componente <code>user</code></p><pre><code class="language-js">import React, { useState } from "react";
import GoogleSignin from "../img/btn_google_signin_dark_pressed_web.png";

const NavBar = () =&gt; {
  const [user, setUser] = useState(false);
  const googleSignIn = () =&gt; {
    setUser(true);
  };
  const signOut = () =&gt; {
    setUser(false);
  };
  return (
    &lt;nav className="nav-bar"&gt;
      &lt;h1&gt;React Chat&lt;/h1&gt;
      {user ? (
        &lt;button onClick={signOut} className="sign-out" type="button"&gt;
          Sign Out
        &lt;/button&gt;
      ) : (
        &lt;button className="sign-in"&gt;
          &lt;img
            onClick={googleSignIn}
            src={GoogleSignin}
            alt="sign in with google"
            type="button"
          /&gt;
        &lt;/button&gt;
      )}
    &lt;/nav&gt;
  );
};
export default NavBar;</code></pre><p>Hagamos un cambio en el componente <strong>NavBar,</strong> importando lo siguiente:</p><pre><code class="language-js">import { auth } from "../firebase";
import { useAuthState } from "react-firebase-hooks/auth";
import { GoogleAuthProvider, signInWithRedirect } from "firebase/auth";</code></pre><p>Reemplaza el estado del usuario con el siguiente código:</p><p><code>const [user] = useAuthState(auth);</code></p><p>Y edita las funciones googleSignIn y signOut:</p><pre><code class="language-js">const googleSignIn = () =&gt; {
  const provider = new GoogleAuthProvider();
  signInWithRedirect(auth, provider);
};
const signOut = () =&gt; {
  auth.signOut();
};</code></pre><p>La función <code>useAuthState</code> se dispara en el momento que el usuario se loguea o desloguea, permitiéndonos acceder a los detalles del usuario. Actualmente, el estado del usuario es <code>null</code>, una vez que te logueas, el estado del usuario cambiará a la información suministrada por el método de autenticación (en este caso, Google).</p><p>En la función <code>googleSignIn</code>, le indicamos a Firebase que el el usuario quiere autenticarse con Google usando el <code>GoogleAuthProvider()</code>. También lo redirige a la página de inicio de sesión de Google.</p><p>Luego de el correcto inicio de sesión del usuario, sus datos son almacenados en <code>auth</code>, y el usuario es redireccionado a la app. La función <code>signOut</code> borra la información almacenada de autenticación, retornando ésta a <code>null</code>. El nuevo estado almacenado también determina qué botón debe renderizarse.</p><p>Agreguemos también autenticación a nuestro archivo <strong>App.js</strong>. Importa lo siguiente:</p><pre><code class="language-js">import { auth } from "./firebase";
import { useAuthState } from "react-firebase-hooks/auth";</code></pre><p>Agrega el nuevo user state, para que podamos renderizar el componente <strong>Welcome</strong> si el usuario no está logueado o el componente <strong>Chatbox</strong> si el usuario ya se autenticó.</p><pre><code class="language-js">const [user] = useAuthState(auth);</code></pre><p>El codigo final debe lucir así:</p><pre><code class="language-js">import { auth } from "./firebase";
import { useAuthState } from "react-firebase-hooks/auth";
import "./App.css";
import NavBar from "./components/NavBar";
import ChatBox from "./components/ChatBox";
import Welcome from "./components/Welcome";

function App() {
  const [user] = useAuthState(auth);
  return (
    &lt;div className="App"&gt;
      &lt;NavBar /&gt;
      {!user ? &lt;Welcome /&gt; : &lt;ChatBox /&gt;}
    &lt;/div&gt;
  );
}
export default App;</code></pre><p>Al probar nuestras nuevas funciones de sign-in y sign-out, veremos lo siguiente:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2023/01/ezgif-4-b6465d1647-1.gif" class="kg-image" alt="ezgif-4-b6465d1647-1" width="600" height="400" loading="lazy"><figcaption>App demo</figcaption></figure><p>Ahora, hagamos lo mismo con el componente <strong>Welcome, </strong>que ahora tiene el siguiente código:</p><pre><code class="language-js">import React from "react";
import GoogleSignin from "../img/btn_google_signin_dark_pressed_web.png";

const Welcome = () =&gt; {
  const googleSignIn = () =&gt; {};

  return (
    &lt;main className="welcome"&gt;
      &lt;h2&gt;Welcome to React Chat.&lt;/h2&gt;
      &lt;img src="/logo512.png" alt="ReactJs logo" width={50} height={50} /&gt;
      &lt;p&gt;Sign in with Google to chat with with your fellow React Developers.&lt;/p&gt;
      &lt;button className="sign-in"&gt;
        &lt;img
          onClick={googleSignIn}
          src={GoogleSignin}
          alt="sign in with google"
          type="button"
        /&gt;
      &lt;/button&gt;
    &lt;/main&gt;
  );
};
export default Welcome;</code></pre><p>Importaremos lo siguiente:</p><pre><code class="language-js">import { auth } from "../firebase";
import { GoogleAuthProvider, signInWithRedirect } from "firebase/auth";</code></pre><p>y tambien editaremos la funcion googleSignIn:</p><pre><code class="language-js">const googleSignIn = () =&gt; {
    const provider = new GoogleAuthProvider();
    signInWithRedirect(auth, provider);
};</code></pre><p>Ahora, podremos loguearnos desde el botón que se renderiza en el componente <strong>Welcome</strong>:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2023/01/video2-1.gif" class="kg-image" alt="video2-1" width="600" height="400" loading="lazy"><figcaption>Updated app demo</figcaption></figure><h3 id="como-enviar-y-almacenar-mensajes-en-firebase-"><strong>Como enviar y almacenar mensajes en Firebase:</strong></h3><p>Actualmente, estamos mostrando un mensaje de prueba de nuestro componente <strong>Message y, </strong>el botón<strong> <strong>Send</strong></strong> no realiza ninguna acción. Cuando ingresamos un mensaje y pulsamos el botón <strong><strong>Send</strong></strong>, queremos que el mensaje se envíe de inmediato a la aplicación.</p><p>Así, que editemos el componente <strong><strong>SendMessage</strong>:</strong> </p><p>Primero, importamos <code>useState</code> de React, <code>auth</code> y <code>db</code> &nbsp;de nuestro archivo de configuración de firebase, y <code>addDoc</code>, <code>collection</code> y <code>serverTimestamp</code> de la librería Firestore.</p><pre><code class="language-js">import React, { useState } from "react";
import { auth, db } from "../firebase";
import { addDoc, collection, serverTimestamp } from "firebase/firestore";</code></pre><p>Crearemos un estado llamado <code>message</code> que inicialmente esté definido como una cadena vacía y se pase como valor a la etiqueta <code>input</code>. La funcion <code>onChange</code> es también agregada a el input, que setea el estado del <code>message</code> en lo que el usuario tipee.</p><pre><code class="language-js">const SendMessage = () =&gt; {
  const [message, setMessage] = useState("");
    
  return (
    &lt;form className="send-message"&gt;
      &lt;input
        ...
        value={message}
        onChange={(e) =&gt; setMessage(e.target.value)}
      /&gt;
      &lt;button type="submit"&gt;Send&lt;/button&gt;
    &lt;/form&gt;
  );
};</code></pre><p>También creamos una función llamada <code>sendMessage</code>, y agregamos el atributo <code>onSubmit</code> en nuestro formulario, que ejecuta la función <code>sendMessage</code> cuando el usuario clickea en el botón <code>Send</code> (enviar). Nótese que el botón debe tener el tipo <code>type="submit"</code> &nbsp;para que la función funcione.</p><pre><code class="language-js"> const sendMessage = async (event) =&gt; {
    event.preventDefault();
    if (message.trim() === "") {
      alert("Enter valid message");
      return;
    }
    const { uid, displayName, photoURL } = auth.currentUser;
    await addDoc(collection(db, "messages"), {
      text: message,
      name: displayName,
      avatar: photoURL,
      createdAt: serverTimestamp(),
      uid,
    });
    setMessage("");
  };
  
  return (
    &lt;form onSubmit={(event) =&gt; sendMessage(event)} className="send-message"&gt;
...</code></pre><p>La función <code>sendMessage</code> es una funcion asincrona. Primero chequea si el el usuario esta intentando enviar una cadena vacía o espacios vacíos como un mensaje y, en caso de que así sea alerta al usuario. </p><p>Si el mensaje no es una cadena vacía, toma del usuario los siguientes datos dela información proporcionada por <code>auth</code> al logguearse: <strong>uid, displayName </strong>y <strong>photoURL.</strong> Estos datos corresponden con el identificador único del usuario, su nombre y la URL de la foto del usuario, respectivamente.</p><p>Luego, usa la función <code>addDoc()</code> para crear un <strong>documento</strong> dentro de la <strong>colección</strong> <strong>messages</strong> de nuestra <strong>base de datos, </strong>a la que accede gracias al archivo que importamos. En caso de que la <strong>colección</strong> no exista, crea una por nosotros. </p><p>También crea un par de <strong>llave-valor</strong>, guardando nuestro <strong>mensaje</strong> en <strong>text, displayName </strong>en <strong>name, </strong>guardando el momento en el que el mensaje fue guardado en nuestra base de datos en la columna <strong>createAt</strong>, y el <strong>uid</strong>.</p><p>Estos pares de llave-valor, conforman los datos de nuestro documento. Una vez que se completa la acción, se restablece el estado del mensajea una cadena vacía.</p><h3 id="como-recuperar-mensajes-de-nuestra-base-de-datos"><strong>Como recuperar mensajes de nuestra base de datos</strong></h3><p>Luego de enviar el mensaje del usuario, debemos mostrarlo en la pantalla. Vayamos a nuestro componente <strong>chatBox</strong> e importemos lo siguiente:</p><pre><code class="language-js">import { useEffect, useRef, useState } from "react";
import {
  query,
  collection,
  orderBy,
  onSnapshot,
  limit,
} from "firebase/firestore";
import { db } from "../firebase";</code></pre><p>Creamos el hook <code>useEffect</code> que correra cada vez que se realizan cambios en el thatroom, por ejemplo enviar o borrar un mensaje.</p><pre><code class="language-js">useEffect(() =&gt; {
  const q = query(
    collection(db, "messages"),
    orderBy("createdAt", "desc"),
    limit(50)
  );
  const unsubscribe = onSnapshot(q, (QuerySnapshot) =&gt; {
    const fetchedMessages = [];
    QuerySnapshot.forEach((doc) =&gt; {
      fetchedMessages.push({ ...doc.data(), id: doc.id });
    });
    const sortedMessages = fetchedMessages.sort(
      (a, b) =&gt; a.createdAt - b.createdAt
    );
    setMessages(sortedMessages);
  });
  return () =&gt; unsubscribe;
}, []);</code></pre><p>En el hook <code>useEffect</code>, tenemos la constante <code>q</code>, una consulta de Firebase que busca los mensajes dentro de la base de la colección <strong>messages</strong> de nuestra base de datos, luego ordena los documentos obtenidos basados en la llave <strong>createAt </strong>y devuelve un máximo de <strong>50</strong> documentos (mensajes guardados)</p><p>La constante <code>unsubscribe</code> representa la función <code>onSnapshot</code>, que escucha los cambios en el documento, esta función tiene un arreglo vacío llamado <code>messages</code>.</p><p>El bucle <code>forEach</code> itera entre todos los <strong>documentos</strong> de la <strong>colección</strong> y guarda la información en un nuevo arreglo. Luego, asigna el arreglo inicial de mensajes al nuevo arreglo de mensajes.</p><p>También usamos el <strong>método map</strong> en nuestro arreglo de mensajes para &nbsp;cada mensaje/documento en nuestro componente <strong>message</strong>.</p><pre><code class="language-js">{messages?.map((message) =&gt; (
  &lt;Message key={message.id} message={message} /&gt;
))}</code></pre><p>El codigo completo luce asi:</p><pre><code class="language-js">import React, { useEffect, useRef, useState } from "react";
import {
  query,
  collection,
  orderBy,
  onSnapshot,
  limit,
} from "firebase/firestore";
import { db } from "../firebase";
import Message from "./Message";
import SendMessage from "./SendMessage";

const ChatBox = () =&gt; {
  const [messages, setMessages] = useState([]);
  const scroll = useRef();

  useEffect(() =&gt; {
    const q = query(
      collection(db, "messages"),
      orderBy("createdAt", "desc"),
      limit(50)
    );

    const unsubscribe = onSnapshot(q, (QuerySnapshot) =&gt; {
      const fetchedMessages = [];
      QuerySnapshot.forEach((doc) =&gt; {
        fetchedMessages.push({ ...doc.data(), id: doc.id });
      });
      const sortedMessages = fetchedMessages.sort(
        (a, b) =&gt; a.createdAt - b.createdAt
      );
      setMessages(sortedMessages);
    });
    return () =&gt; unsubscribe;
  }, []);

  return (
    &lt;main className="chat-box"&gt;
      &lt;div className="messages-wrapper"&gt;
        {messages?.map((message) =&gt; (
          &lt;Message key={message.id} message={message} /&gt;
        ))}
      &lt;/div&gt;
      {/* when a new message enters the chat, the screen scrolls down to the scroll div */}
      &lt;span ref={scroll}&gt;&lt;/span&gt;
      &lt;SendMessage scroll={scroll} /&gt;
    &lt;/main&gt;
  );
};

export default ChatBox;</code></pre><p>Vayamos a nuestro componente <strong>message</strong>, y rendericemos los datos recibidos en el navegador.</p><pre><code class="language-js">import React from "react";
import { auth } from "../firebase";
import { useAuthState } from "react-firebase-hooks/auth";
const Message = ({ message }) =&gt; {
  const [user] = useAuthState(auth);

  return (
    &lt;div
      className={`chat-bubble ${message.uid === user.uid ? "right" : ""}`}&gt;
      &lt;img
        className="chat-bubble__left"
        src={message.avatar}
        alt="user avatar"
      /&gt;
      &lt;div className="chat-bubble__right"&gt;
        &lt;p className="user-name"&gt;{message.name}&lt;/p&gt;
        &lt;p className="user-message"&gt;{message.text}&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
};
export default Message;
</code></pre><p>Importamos <code>auth</code> y <code>useAuthState</code>, y almacenamos los datos del usuario en &nbsp;<code>user</code>. Deconstruimos el <code>prop</code> <strong>message</strong> y asignamos el avatar al atributo <code>src</code> del componente img. También reemplazamos el nombre y el mensaje "de prueba" con el mensaje obtenido desde <strong>message</strong>. </p><p>También aplicamos una condición al estilo CSS según el <code>uid</code> del autor del mensaje, entonces si el <code>uid</code> del autor del mensaje es el mismo que el del usuario logueado, se aplica al div el estilo definido en el selector <strong>derecho</strong>; en caso contrario no se agrega ningún estilo adicional.</p><p>Actualmente, todos &nbsp;los mensajes se posicionan a la izquierda, así que si el autor del mensaje es el usuario logueado, sus mensajes se posicionaran a la derecha. Veamos esa dinámica en acción en el navegador:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2023/01/video3-1.gif" class="kg-image" alt="video3-1" width="600" height="400" loading="lazy"><figcaption>Demostración de la app actualizada</figcaption></figure><p>El mensaje es enviado y almacenado en nuestra base de datos, luego todos los mensajes se recuperan y la sala es actualizada en tiempo real con los mensajes nuevos.</p><p>El nombre y el avatar de cada usuario son &nbsp;mostrados en cada tarjeta, pero también podemos ver que el chat no se desliza automáticamente hacia abajo cuando llega un nuevo mensaje. Vamos a arreglar eso.</p><h3 id="como-hacer-que-el-chat-se-desplace-hasta-el-final"><strong>Como hacer que el chat se desplace hasta el final</strong></h3><p>Vayamos al archivo <strong>ChatBox.js</strong>, importemos el hook <code>useRef</code> y creemos una constante llamada scroll:</p><pre><code class="language-js">import React, { useEffect, useRef, useState } from "react";
...
const scroll = useRef();</code></pre><p>Crearemos un elemento <code>span</code> con un atributo <code>ref</code> conectado al valor de <strong>scroll</strong>,y , también pasamos el &nbsp;<strong>s<strong>crol</strong>l </strong>en nuestro componente<strong> message.</strong></p><p>Luego, creamos un elemento <code>span</code> con un atributo <code>ref</code> cuyo valor es <strong>scroll</strong>, y también pasamos <strong>scroll</strong> a nuestro componente <code>SendMessage</code>:</p><pre><code class="language-js">&lt;main className="chat-box"&gt;
   ...
   {/* when a new message enters the chat, the screen scrolls dowwn to the scroll div */}
   &lt;span ref={scroll}&gt;&lt;/span&gt;
   &lt;SendMessage scroll={scroll} /&gt;
&lt;/main&gt;</code></pre><p>Luego vamos al componente <strong>Messages</strong>, accedemos a la constante scroll, y agregamos <code>scroll.current.scrollIntoView({ behavior: "smooth" })</code> al final de nuestra función <code>sendMessage</code>.</p><p>Este código le indica al navegador que el scroll span debe ser visible después de enviar un mensaje. Por eso ponemos la etiqueta <code>span</code> al final de cada mensaje.</p><pre><code class="language-js">const SendMessage = ({ scroll }) =&gt; {

  const sendMessage = async (event) =&gt; {
   ...
    setMessage("");
    scroll.current.scrollIntoView({ behavior: "smooth" });
  };
  ...
};</code></pre><p>Volviendo al navegador, deberíamos ver que el chat se desplaza automáticamente hasta el final cuando del usuario envía un mensaje.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2023/01/video4-1.gif" class="kg-image" alt="video4-1" width="600" height="400" loading="lazy"><figcaption>Demo mostrando como el chat se desliza hasta el final con un nuevo mensaje.</figcaption></figure><h2 id="como-agregar-dominios-autorizados"><strong>Como agregar dominios autorizados</strong></h2><p>Cuando desplegamos nuestra aplicacion en React, es indispensable agregar nuestro dominio a la lista de dominios autorizados en Firebase. Este paso, asegura que nuestra app se comunique correctamente con los servicios de Firebase, veamos como hacerlo:</p><p>En la consola de Firebase, navega hasta la sección <strong>Autenticación </strong>y haz click en la pestaña de <strong>configuración.</strong> Deslízate hasta la parte de <strong>Dominios autorizados; </strong>a continuación clickea en el botón<strong> agregar un dominio. </strong>Luego agrega el o los dominios donde la aplicación será desplegada. </p><p>Por ejemplo, si desplegaras la aplicación en la dirección <a href="https://my-react-chat-app.com/" rel="noreferrer nofollow noopener">https://my-react-chat-app.com</a>, ingresa <code>my-react-chat-app.com</code> como un dominio autorizado, y clickea el boton <strong>agregar</strong> para guardar los cambios.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2025/03/firestone-agregar-dominio-1.png" class="kg-image" alt="firestone-agregar-dominio-1" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2025/03/firestone-agregar-dominio-1.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2025/03/firestone-agregar-dominio-1.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/2025/03/firestone-agregar-dominio-1.png 1366w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Agregando el dominio donde desplegaras tu app a la lista de dominios autorizados, le brindas permisos a los servicios de Firestone para ser accedidos desde ese dominio. Si no hiciéramos esto, encontraríamos errores al intentar establecer conexión o realizar operaciones con Firebase.</p><h2 id="para-terminar"><strong>Para terminar</strong></h2><p>Y, así es como llegamos al final de la construcción de esta aplicación de chat en tiempo real, ¡felicitaciones!.</p><p>En este tutorial, aprendimos a usar Firebase y React para crear una aplicacion de &nbsp;chat en tiempo real. También autenticamos a los usuarios usando el método de logueo por cuenta de Google de Firetone y, guardamos los mensajes del chat usando Cloud Firestore. Finalmente, aprendimos a usar algunos servicios y librerías de Firestone.</p><p>Puedes encontrar el código de este proyecto en <a href="https://github.com/Timonwa/react-chat">GitHub</a> y puedes probar la aplicación desplegada usando el siguiente <a href="https://react-chat-timonwa.vercel.app/">enlace</a>.</p><p>Si disfrutaste este articulo, por favor compártelo para ayudar a otros desarrolladores, también puedes visitar mi <a href="https://blog.timonwa.com/">blog</a> para leer mas artículos o puedes seguirme en &nbsp;<a href="https://twitter.com/timonwa_">Twitter</a> o <a href="https://www.linkedin.com/in/timonwa/">LinkedIn</a>.</p><p>Hasta la próxima, byeeeeee!</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2025/03/HoDL1vbXj-1-1-.gif" class="kg-image" alt="HoDL1vbXj-1-1-" width="600" height="400" loading="lazy"></figure> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Comprueba si un elemento está presente en un arreglo en JavaScript: JS contiene con Array.includes() ]]>
                </title>
                <description>
                    <![CDATA[ Puedes utilizar el método includes() en JavaScript para comprobar si un elemento existe en un arreglo, también lo puedes utilizar para comprobar si una substring existe dentro de una cadena. Este método retornarátrue (verdadero) si el elemento está presente en el arreglo, yfalse (falso) si el elemento no existe en ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/comprobar-si-un-elemento-esta-presente-en-un-arreglo-en-javascript-utilizando-el-metodo-includes/</link>
                <guid isPermaLink="false">66063a286e403a04017ccd2a</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lucas Agustín Morales Romero ]]>
                </dc:creator>
                <pubDate>Sat, 04 May 2024 23:59:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2024/03/pankaj-patel-1IW4HQuauSU-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/check-if-an-item-is-in-an-array-in-javascript-js-contains-with-array-includes/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Check if an Item is in an Array in JavaScript – JS Contains with Array.includes()</a>
      </p><p>Puedes utilizar el método <code>includes()</code> en JavaScript para comprobar si un elemento existe en un arreglo, también lo puedes utilizar para comprobar si una substring existe dentro de una cadena.</p><p>Este método retornará &nbsp;<code>true</code> (verdadero) si el elemento está presente en el arreglo, y &nbsp;<code>false</code> (falso) si el elemento no existe en dicho arreglo.</p><p>En este artículo, verás como usar el método <code>includes()</code> en JavaScript para corroborar si un elemento, o una substring existe en un arreglo.</p><h2 id="como-corroborar-si-un-elemento-est-dentro-de-un-arreglo-utilizando-el-m-todo-array-includes-"><strong>Como corroborar si un elemento está dentro de un arreglo utilizando el método<strong> </strong></strong><code><strong><strong>Array.includes()</strong></strong></code></h2><p>Esta es la sintaxis usada por el método <code>includes()</code> para verificar si un elemento está dentro de un arreglo:</p><p><code>array.includes(item, fromIndex)</code></p><p>Vamos a analizar la sintaxis parte por parte:</p><p><code>array</code> es el nombre del arreglo en el que queremos verificar la existencia del objeto que queremos buscar.</p><p>El método <code>includes()</code> recibe dos parámetros: <code>item</code> y <code>fromIndex</code>.</p><ul><li><code>item</code> &nbsp;es el elemento que queremos encontrar.</li><li><code>fromIndex</code>, el cual es un parámetro opcional, especifica el índice desde el que se quiere realizar la búsqueda. Si no incluyes ese parámetro, el parámetro predefinido será 0 (el primer elemento).</li></ul><p>A continuación te presento un par de ejemplos de cómo usar el método <code>includes()</code> para verificar si un elemento está presente en un arreglo:</p><p><code>const numeros = [ 1, 3, 5, 7]; console.log(numeros.includes(3)); // true</code></p><p>En el ejemplo, creamos un arreglo llamado <code>números</code> con cuatro elementos: 1, 3, 5, 7.</p><p>Usando notación de punto, accedemos al método <code>includes()</code> del arreglo <code>numeros</code>.</p><p>Como parámetro, le pasamos un 3 al método <code>includes()</code>, este es el objeto que queremos encontrar.</p><p>Finalmente, obtenemos <code>true</code> (verdadero) porque 3 existe en el arreglo <code>numeros</code>.</p><p>Ahora, intentemos buscar un número que no existe en el arreglo:</p><p>‌<code>const numeros = [ 1, 3, 5, 7]; console.log(numeros.includes(8)); // false </code></p><p>Como era de esperarse, obtenemos <code>false</code> (falso) como respuesta debido a que 8 no es un objeto que exista en el arreglo <code>numeros</code>.</p><h2 id="como-corroborar-si-un-elemento-est-dentro-de-un-arreglo-utilizando-el-m-todo-array-includes-pero-esta-vez-empezando-desde-un-ndice-espec-fico"><strong>Como corroborar si un elemento está dentro de un arreglo utilizando el método<strong> </strong></strong><code><strong><strong>Array.includes()</strong></strong></code><strong>, pero esta vez empezando desde un índice específico</strong></h2><p>En la última parte, vimos cómo verificar si un elemento existe en un arreglo sin utilizar el segundo parámetro del método <code>includes()</code>.</p><p>Como recordatorio, el segundo parámetro se utiliza para especificar el índice desde el cual se comenzará a buscar dentro del arreglo.</p><p>El índice de los arreglos comienza en 0, por lo que el primer elemento es el índice 0, el segundo es el índice 1, el tercero es el índice 2 y así sucesivamente.</p><p>Aquí te muestro un ejemplo de como usar el segundo parámetro en el método &nbsp;<code>includes()</code>:</p><p>‌<code>const numeros = [ 1, 3, 5, 7]; console.log(numeros.includes(3,2)); // false</code></p><p>El ejemplo nos retorna <code>false</code> (falso), incluso cuando tenemos el valor 3 dentro del arreglo, ahora, aquí está el porqué:</p><p>Usando el segundo parámetro, le pedimos al método <code>includes()</code> que buscará el número 3, pero empezando en el índice 2: <code>numeros.includes(3,2)</code>.</p><p>Este es el arreglo: [ 1, 3, 5, 7]</p><p>Índice 0 = 1.</p><p>Índice 1 = 3.</p><p>Índice 2 = &nbsp;5.</p><p>Índice 3 = 7.</p><p>Así que, comenzando desde el segundo índice, en el que encontramos el valor 5, solo disponemos de dos índices en los cuales buscar , en los cuales se encuentran los valores 5 y 7, este es el porqué al buscar el valor 3 dentro del arreglo, este nos devuelve <code>false</code> (falso), aun cuando este valor si exista en el arreglo.</p><p>Si cambias el índice para que comience la búsqueda desde el índice 1, obtendremos <code>true</code> (verdadero) como respuesta porque 3 si existe en ese rango:</p><p>‌<code>const numeros = [ 1, 3, 5, 7]; console.log(numeros.includes(3,1)); // true</code>‌</p><h2 id="c-mo-verificar-si-una-substring-existe-dentro-de-una-cadena-de-texto-en-javascript-usando-el-m-todo-includes-"><strong>Cómo verificar si una <strong>Substring </strong>existe dentro de una cadena de texto<strong> </strong>e<strong>n JavaScript</strong> usando<strong> </strong>el método<strong> </strong></strong><code><strong><strong>includes()</strong></strong></code></h2><p>De forma similar a los ejemplos anteriores, podemos utilizar el método <code>includes()</code> mediante la notación de punto para buscar una substring dentro de una cadena de texto.</p><p>Así es como la sintaxis luce:</p><p><code>string.includes(substring, fromIndex)</code></p><p>Este es un ejemplo:</p><p>‌<code>const bio = "Soy un desarrollador web"; console.log(bio.includes("web")); // true</code></p><p>En el ejemplo, la variable <code>bio</code> contiene la siguiente cadena de texto: "Soy un desarrollador web".</p><p>Usando el método <code>includes()</code> buscamos la substring "web".</p><p>Obtenemos <code>true</code> (verdadero) como respuesta porque "web" se encuentra dentro de la cadena de texto <code>bio</code>.</p><p>Al igual que en el ejemplo anterior, podemos pasarle el segundo parámetro para especificar desde donde queremos empezar a buscar, pero en las cadenas de texto, cada carácter representa un índice de la cadena (incluso los espacios en blanco)</p><p>Aquí te presento un ejemplo para ilustrar la búsqueda con</p><p><code>let bio = "Soy un desarrollador web"; console.log(bio.includes("web",23)); // false</code></p><p>Obtenemos <code>false</code> (falso) porque el índice 23 es la "e" en "web".</p><p>Empezando en el índice 23, la cadena luce así: "eb", la substring "web" no existe en &nbsp;esa porción de la cadena, por lo que el método nos retorna <code>false</code> (falso).</p><h2 id="resumen"><strong>Resumen</strong></h2><p>En este artículo, hablamos sobre el método <code>includes()</code> de JavaScript. Lo usamos para verificar la existencia de un elemento en un arreglo y de una substring en una cadena de texto.</p><p>Vimos algunos ejemplos de su uso con y sin especificar el índice desde el que comenzar a buscar.</p><p>Finalmente, vimos como usar el método <code>includes()</code> &nbsp;para verificar la existencia de una substring dentro de una cadena de texto, tanto, en toda la cadena como desde un índice específico.</p><p>¡Feliz día programando!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Arreglos en Javascript: Cómo quitar y agregar elementos ]]>
                </title>
                <description>
                    <![CDATA[ Los arreglos son estructuras de datos comunes en JavaScript, y es importante saber cómo trabajar con ellos. Las operaciones básicas incluyen agregar o remover elementos desde el principio, el final o desde un índice en particular. En este artículo, aprenderemos cómo trabajar con los métodos propios de los arreglos: pop(), ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/arreglos-en-javascript-como-quitar-y-agregar-elementos-de-un-arreglo/</link>
                <guid isPermaLink="false">661b0d331238a40479c58e93</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lucas Agustín Morales Romero ]]>
                </dc:creator>
                <pubDate>Thu, 02 May 2024 19:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2024/04/mohammad-rahmani-unwXUc_Pqi4-unsplash.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-add-and-remove-js-array-elements/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Add and Remove Elements from Arrays in JavaScript</a>
      </p><p>Los arreglos son estructuras de datos comunes en JavaScript, y es importante saber cómo trabajar con ellos.</p><p>Las operaciones básicas incluyen agregar o remover elementos desde el principio, el final o desde un índice en particular.</p><p>En este artículo, aprenderemos cómo trabajar con los métodos propios de los arreglos: <code>pop()</code>, <code>push()</code>, <code>shift()</code> y <code>unshift()</code>. También, veremos cómo trabajar con el método <code>splice()</code>, el cual nos permite modificar el arreglo agregando o removiendo elementos en un índice específico.</p><h2 id="-qu-es-un-arreglo-en-javascript">¿Qué es un arreglo en JavaScript?</h2><p>Antes de que nos sumerjamos en los diferentes métodos de la clase Arreglo, primero tenemos que entender qué es un arreglo en JavaScript.</p><p>Un arreglo, es un tipo de estructura de datos que se usa para guardar colecciones de elementos, esta puede ser de múltiples tipos al mismo tiempo (<em>como números, cadenas de texto, booleanos [verdadero o falso], otros arreglos o, incluso objetos)</em> o de un solo tipo<strong> </strong><em><strong>(a diferencia de otros lenguajes de tipados como C++, donde los arreglos son de un solo tipo a la vez). </strong></em></p><p>Aquí te presento un ejemplo de un arreglo de nombres:</p><pre><code class="language-javascript">let nombres = ["Maria", "Victoria", "Santino"];</code></pre><p>Para acceder a un elemento del arreglo, debes hacerlo escribiendo el nombre del arreglo, y entre corchetes el índice del elemento al que quieres acceder, este índice comienza en cero y se incrementa de uno en uno.</p><p>Volviendo al ejemplo anterior si quisiera obtener el primer nombre deberías hacerlo de este modo:</p><pre><code class="language-javascript">nombres[0]; // "Maria"</code></pre><p>Ahora, digamos que se quiere acceder al último elemento del arreglo. En ese caso puedes hacer uso de la propiedad <code>length()</code> la cual nos retornará la longitud del arreglo y le restamos 1 (recuerda que el índice del arreglo comienza en cero así, que en nuestro arreglo el último de los 3 elementos sería el elemento con sub-índice 2).</p><pre><code class="language-javascript">nombres[nombres.length - 1]; // "Santino"</code></pre><h2 id="c-mo-remover-un-elemento-al-final-del-arreglo"><strong>Cómo remover un elemento al final del arreglo</strong></h2><p>Llega el momento de hablar de uno de los primero métodos que veremos en el artículo: el método <code>pop()</code>. Este método nos permite remover el último elemento de un arreglo; de ese modo podemos asignarlo en otra variable pero, <strong>hay que tener en cuenta al usarlo ya que este método modifica la estructura del arreglo</strong>.</p><p>Veamos un ejemplo, trabajando nuevamente con nuestro arreglo:</p><pre><code class="language-javascript">// declaramos un arreglo de nombres 
let nombres = ["Maria", "Victoria", "Santino"]; 

// declaramos una variable que contendrá el elemento extraído del arreglo 
let nombreEliminado; 

// asignamos el elemento eliminado del arreglo con el metodo pop en la variable nombreEliminado 
nombreEliminado = nombres.pop(); 

// mostramos en consola el nombre eliminado 
console.log(nombreEliminado); // "Santino" 

// mostramos en consola el contenido del arreglo nombres:
console.log(nombres); // Array(2)["Maria","Victoria"] </code></pre><p>Si utilizamos este método en un arreglo vacío, lo que obtendremos será <code>undefined</code>, veamos cómo se vería en la consola de javascript:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/04/arrayVacio.jpg" class="kg-image" alt="arrayVacio" width="452" height="342" loading="lazy"><figcaption>Ejemplo del método <code>pop()</code> en un arreglo vacío</figcaption></figure><h2 id="c-mo-remover-un-elemento-al-principio-del-arreglo">Cómo remover un elemento al principio del arreglo</h2><p>Llega el momento de hablar de <code>shift()</code>. Este método permite retirar el primer elemento del arreglo y asignarlo en una nueva variable, y al igual que con el método <code>pop()</code> <strong>hay que tener cuidado al utilizarlo ya que este método modifica el arreglo original.</strong></p><p>Volvamos al ejemplo del arreglo de los nombres para ver cómo funciona:</p><pre><code class="language-javascript">// mostramos en consola el contenido del arreglo nombres:
console.log(nombres); // Array(2)["Maria","Victoria"] 

// creamos una variable para extrer el primer nombre 
let otroNombreEliminado; 

// utilizamos el metodo shift() para quitar el primer nombre y asignarlo a la variable que creamos (otroNombreEliminado) 
otroNombreEliminado = nombres.shift(); 

// mostramos en consola el nombre que quitamos
console.log(otroNombreEliminado); // "Maria" 

// mostramos en consola el contenido del arreglo:
console.log(nombres); // Array(1)["Victoria"]</code></pre><p>Al igual que con el método <code>pop()</code>, si utilizamos el método <code>shift()</code> en un arreglo vacío, este nos devolverá el valor primitivo <code>undefined</code>, veamos un ejemplo en la consola de javascript:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/04/arrayVacioConShift.jpg" class="kg-image" alt="arrayVacioConShift" width="417" height="423" loading="lazy"><figcaption>Ejemplo del método <code>shift()</code> en un arreglo vacío</figcaption></figure><h2 id="c-mo-agregar-un-elemento-al-final-del-arreglo"><strong>Cómo agregar un elemento al final del arreglo</strong></h2><p>Digamos que al final de un arreglo queremos agregar otro elemento, en ese caso utilizaremos el método <code>push()</code>: éste nos permite agregar nuevos elementos y nos retornará el tamaño actualizado del arreglo, veámoslo con un ejemplo:</p><pre><code class="language-javascript">// crearemos un arreglo con lenguajes de programacion 
let lenguajes = ["C++", "Java", "Visual Basic"]; 

// creamos una nueva variable para guardar el tamaño del arreglo: 
let tamañoArregloOriginal = lenguajes.length; // 3 

// creamos una nueva variable para guardar el tamaño del arreglo luego de modificarlo 
let tamañoArregloModificado; 

// insertamos dos nuevos lenguajes en el arreglo y guardamos el nuevo tamaño del arreglo en la variable nuevoTamaño: 
tamañoArregloModificado = lenguajes.push("Ruby", "Python"); // 5 

// mostramos el arreglo en consola: 
console.log(lenguajes);  // Array(5)["C++", "Java", "Visual Basic", "Ruby", "Python"]</code></pre><p>Algo interesante que podemos hacer con el método <code>push()</code> es agregar un arreglo a otro arreglo, veámoslo con el ejemplo anterior de los lenguajes:</p><pre><code class="language-javascript">// crearemos un arreglo con lenguajes de programacion 
let lenguajes = ["C++", "Java", "Visual Basic"]; 

// crearemos otro arreglo con dos lenguajes: 
let otrosLenguajes = ["Ruby", "Python"]; 

// creamos una nueva variable para guardar el tamaño del arreglo: 
let tamañoArregloOriginal = lenguajes.length; // 3 

// creamos una nueva variable para guardar el tamaño del arreglo luego de modificarlo 
let tamañoArregloModificado; 

// utilizaremos el metodo push junto con la sintaxis expandida (spread) para concatenar el arreglo otrosLenguajes al final del arreglo lenguajes:
tamañoArregloModificado = lenguajes.push(...otrosLenguajes); // 5 

// mostramos el arreglo en consola: 
console.log(lenguajes); // Array(5)["C++", "Java", "Visual Basic", "Ruby", "Python"]</code></pre><p>En este ejemplo utilizamos el operador de <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Spread_syntax">sintaxis extendida (spread)</a> para sumar el arreglo <em><code>otrosLenguajes[]</code></em> hacia el arreglo original <em><code>lenguajes[]</code></em>.</p><h2 id="c-mo-agregar-elementos-al-principio-de-un-arreglo"><strong>Cómo agregar elementos al principio de un arreglo</strong></h2><p>Ahora nos toca hablar del método <code>unshift()</code>, este nos permite agregar nuevos elementos al principio del arreglo original, trabaja del mismo modo que <code>push</code>, pero la concatenación la realiza al principio, veamos el ejemplo anterior de los lenguajes, pero con el método <code>unshift()</code>:</p><pre><code class="language-javascript">// crearemos un arreglo con lenguajes de programacion 
let lenguajes = ["C++", "Java", "Visual Basic"]; 

// creamos una nueva variable para guardar el tamaño del arreglo: 
let tamañoArregloOriginal = lenguajes.length; // 3 

// creamos una nueva variable para guardar el tamaño del arreglo luego de modificarlo 
let tamañoArregloModificado; 

// insertamos dos nuevos lenguajes en el arreglo (al principio del mismo) y guardamos el nuevo tamaño del arreglo en la variable nuevoTamaño: 
tamañoArregloModificado = lenguajes.unshift("Ruby", "Python"); // 5 

// mostramos el arreglo en consola: 
console.log(lenguajes); // Array(5)["Ruby", "Python", "C++", "Java", "Visual Basic"]</code></pre><h2 id="c-mo-agregar-o-remover-elementos-en-un-ndice-espec-fico-del-arreglo"><strong>Cómo agregar o remover elementos en un índice específico del arreglo</strong></h2><p>Llegamos al último método que cubriremos en este artículo: el método <code>splice()</code>, este nos permite agregar o remover elementos en un índice específico del arreglo, la sintaxis del método es la siguiente:</p><pre><code class="language-javascript">array.splice(inicio[, elementoEliminado[, item1[, item2[, ...]]]])</code></pre><p>Ahora, veamos parte por parte, cómo se compone este método:</p><p>El valor <em><strong>inicio</strong></em>, es un número que puedes ser positivo o negativo. Va a indicar desde dónde se comienza a modificar el arreglo (si es <strong>positivo</strong> las posiciones a las que nos movamos comenzarán a contarse desde el primer elemento, es decir, el índice 0, y si es <strong>negativo</strong> comenzará a contar desde el último elemento hacia atrás).</p><p>Algo interesante es que si ponemos un valor mayor al arreglo, comenzará a modificar desde el final del mismo.</p><p>El valor <em><strong>elementoEliminado</strong></em>, es un número que puede ser negativo o positivo, si es negativo o cero indica que no vamos a eliminar ningún elemento del arreglo, por el contrario si es positivo nos marcará la cantidad de elementos a eliminar, <strong><em>si es mayor al índice del arreglo, eliminará el total.</em></strong></p><p><em><strong>item1, item2, etc...</strong></em> son los valores que insertamos en el arreglo.</p><p>Veámoslo con un ejemplo:</p><pre><code class="language-javascript">// Primero, crearemos un arreglo al que llamaremos sistema solar, que contendra los planetas pertenecientes: 
let sistemaSolar = ["Sol", "Mercurio", "Venus", "Marte", "Jupiter", "Saturno", "Neptuno", "Urano", "Pluton"]; </code></pre><p>Si leemos nuestro ejemplo, vemos que nos falta un planeta, la Tierra, por lo que utilizaremos el método <code>splice()</code> para agregarlo:</p><pre><code class="language-javascript">sistemaSolar.splice(3, 0, "Tierra"); // ["Sol", "Mercurio", "Venus", "Marte", "Tierra", "Jupiter", "Saturno", "Neptuno", "Urano", "Pluton"];
</code></pre><h3 id="repasemos-qu-realizamos-con-el-m-todo-splice-">Repasemos qué realizamos con el método <code>splice</code>:</h3><p>El primer argumento del <code>splice</code>, indica en qué punto nos ubicamos para insertar o quitar el elemento (nos ubicamos en el índice 3, donde se encuentra <em>"Marte").</em></p><p>El segundo argumento, indica si vamos a eliminar o no un elemento, en este caso agregamos, por lo que le pasamos un cero.</p><p>El tercer argumento es el elemento que insertamos, en esta caso una cadena de texto: "Tierra".</p><p><strong><em>Cabe destacar, que siempre que utilicemos el método <code>splice()</code> este nos retornará un arreglo vacío en caso de que insertemos valores:</em></strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/04/spliceRetornoInsertar.jpg" class="kg-image" alt="spliceRetornoInsertar" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/04/spliceRetornoInsertar.jpg 600w, https://www.freecodecamp.org/espanol/news/content/images/2024/04/spliceRetornoInsertar.jpg 843w" sizes="(min-width: 720px) 720px" width="843" height="225" loading="lazy"><figcaption>Ejecución del código de prueba en la consola de JavaScript, con el retorno de un arreglo tras ejecutar <code>splice()</code></figcaption></figure><p>Sigamos trabajando con nuestro arreglo. Si revisamos el arreglo, veremos que al principio del mismo, tenemos listado al Sol, y éste es una estrella, no un planeta, por lo que vamos a removerlo con <code>splice()</code> y guardarlo en otro arreglo:</p><pre><code class="language-javascript">let indice = sistemaSolar.indexOf("Sol"); 
let estrella[]; 

if (indice !== -1) { estrella = sistemaSolar.splice(indice, 1); }</code></pre><h3 id="repasemos-el-ltimo-ejemplo-">Repasemos el último ejemplo:</h3><p>Primero definimos una variable auxiliar llamada índice, a la cual le asignamos utilizando el método <code>indexOf()</code> el índice de la cadena "Sol", para luego utilizarla en el <code>splice</code> como índice a retirar.</p><p>Luego, creamos un arreglo llamado estrella donde guardaremos el elemento que <code>splice</code> nos devuelve.</p><blockquote>El método <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf">indexOf()</a> realiza la <em><strong>comparación estricta</strong></em> de la cadena que le pasamos y devuelve el primer índice en el que aparece, y en caso de que esta cadena no exista, retorna "-1".</blockquote><p>Luego, con un condicional, verificamos que el índice no sea igual a -1.</p><p>Finalmente, guardamos en el arreglo estrella el <code>splice</code>, pasándole como primer argumento el índice, y como segundo argumento la cantidad a remover (en este caso, 1 elemento).</p><h2 id="conclusiones"><strong>Conclusiones</strong></h2><p>En este artículo aprendimos cómo utilizar los métodos <code>pop</code>, <code>push</code>, <code>shift</code> y <code>unshift</code> pertenecientes al objeto arreglo, extremadamente útiles al momento de agregar o remover un elemento al principio o al final del arreglo.</p><p>También aprendimos a utilizar el método <code>splice</code> para remover o agregar un elemento al arreglo en una posición específica.</p><p><strong>Recuerde, que todos los métodos vistos cambian la estructura del arreglo.</strong></p><p>Espero que hayas encontrado este artículo interesante, disfruta el día programando <strong>(¡y aprendiendo algo nuevo!)</strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Vectores en C++ : Cómo inicializar un vector en un constructor en C++ ]]>
                </title>
                <description>
                    <![CDATA[ Cuando estás trabajando con una colección de variables o de datos en programación, usualmente los guardas en un tipo de dato específico. En C++, puedes guardarlos en arreglos, estructuras, vectores, cadenas de texto y la lista sigue. Si bien estas estructuras de datos tiene sus características distintivas, en este artículo ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/vectores-en-c-como-inicializar-un-vector-en-un-constructor-en-c/</link>
                <guid isPermaLink="false">66087de26e403a04017ccf70</guid>
                
                    <category>
                        <![CDATA[ c++ ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lucas Agustín Morales Romero ]]>
                </dc:creator>
                <pubDate>Tue, 16 Apr 2024 19:43:37 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2024/03/uday-awal-UjJWhMerJx0-unsplash--2-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/cpp-vector-how-to-initialize-a-vector-in-a-constructor/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">C++ Vector – How to Initialize a Vector in a Constructor in C++</a>
      </p><p>Cuando estás trabajando con una colección de variables o de datos en programación, usualmente los guardas en un tipo de dato específico.</p><p>En C++, puedes guardarlos en arreglos, estructuras, vectores, cadenas de texto y la lista sigue. Si bien estas estructuras de datos tiene sus características distintivas, en este artículo nos vamos a concentrar en los múltiples métodos para inicializar vectores.</p><p>Pero antes, hablemos un poco de los vectores y que los hace destacarse cuando trabajamos con colecciones en C++.</p><h2 id="-qu-son-los-vectores-en-c-"><strong>¿Qué son los vectores en C++?</strong></h2><p>A diferencia de los arreglos, donde la memoria es asignada de forma estática, los vectores nos permiten crear estructuras de datos más dinámicas.</p><p>Este es un ejemplo de un arreglo en C++:</p><pre><code class="language-C++">#include &lt;iostream&gt;
using namespace std;

int main() {
    string nombres[3] = {"Nicolas", "Matias", "Tomas"};
    cout &lt;&lt; nombres[1] &lt;&lt; endl;
    // Matias
}
 </code></pre><p>El arreglo del código de ejemplo fue creado y reservo en memoria el espacio suficiente para contener solo 3 elementos, en el caso de que quisiéramos agregar nuevos elementos generando un nuevo índice, nos daría como resultado un error. </p><p>Con los vectores, las cosas son un poquito diferente, cuando lo definimos, no tenemos que especificar la capacidad que tendrá, tras bambalinas, el espacio en memoria del vector se modifica al mismo tiempo que cambia el tamaño del vector. </p><h2 id="sintaxis-de-los-vectores-en-c-"><strong>Sintaxis de los vectores en C++</strong></h2><p>Declarar un <code>vector</code> es diferente de inicializarlo, Declararlo significa crear un nuevo <code>vector</code>, mientras que inicializarlo es insertarle elementos en él.</p><p>Así es como se ve la sintaxis de un vector:</p><pre><code class="language-txt">vector &lt;tipo_de_dato&gt; nombre_de_vector</code></pre><p>Cada nuevo <code>vector</code> debe ser declarado usando la palabra clave <strong>vector, </strong>seguido por el tipo de dato que queremos almacenar encerrado entre paréntesis angulares (el vector puede contener varios tipos de datos: cadenas, enteros, caracteres y la lista sigue), por último debemos especificar el nombre del vector, el cual puede ser cualquiera que nosotros decidamos, aunque siempre es conveniente utilizar nombres que hagan nuestro código lo más legible posible.</p><p>Cabe aclarar que debemos escribir la directiva <code>include &lt;vector&gt;</code> al inicio del archivo para poder usar los vectores.</p><h2 id="c-mo-inicializar-un-vector-en-c-"><strong>Cómo inicializar un vector en C++</strong></h2><p>En esta sección, veremos las diferentes maneras de inicializar un <code>vector</code> en C++, las dividiremos en subsecciones con su respectivo ejemplo. </p><p>Comencemos con la manera más básica.</p><h3 id="c-mo-inicializar-un-vector-en-c-usando-el-m-todo-push_back-"><strong>Cómo inicializar un vector en C++ usando el método <code>push_back()</code></strong></h3><p><strong><code>push_back()</code> </strong>es uno de los varios métodos que podemos usar para interactuar con los vectores. <code>Push_back()</code> toma el parámetro que le demos y lo inserta en el índice final del vector.</p><p>Aquí tenemos un ejemplo:</p><pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int main() {
	//declaramos el vector "miVector"
    vector&lt;int&gt; miVector;
	//ahora, inicializamos el vector usando push_back()
	miVector.push_back(5);
	miVector.push_back(10);
	miVector.push_back(15);

	for (int x : miVector)
		cout &lt;&lt; x &lt;&lt; " ";
		// 5 10 15 
}
</code></pre><p>En el ejemplo, declaramos el <code>vector</code>, <code>miVector</code> usando la sentencia <code>vector&lt;int&gt; miVector;</code>.</p><p>Luego, usando el método <code>push_back()</code> le insertamos tres valores (5,10,15)</p><p>Finalmente, usando un bucle <strong>for</strong>, iteramos en el vector para mostrar en consola los valores.</p><h3 id="como-inicializar-un-vector-al-mismo-tiempo-que-lo-declaramos"><strong>Como inicializar un vector al mismo tiempo que lo declaramos</strong></h3><p>Al igual que con los arreglos, podemos asignar valores al vector al momento que lo declaramos. <br><br>Veamos el siguiente ejemplo: </p><pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int main() {
	//declaramos e inicializamos el vector miVector
    vector&lt;int&gt; miVector{ 5, 10, 15 };

	for (int x : miVector)
		cout &lt;&lt; x &lt;&lt; " ";
		// 5 10 15 
}
</code></pre><p>En este ejemplo, en la misma línea declaramos e inicializamos el vector.</p><p>Una vez que los números son asignados al <code>vector</code>, lo recorremos y, posteriormente, los imprimimos en consola.</p><p>Habrá notado, que entre paréntesis angulares encerré el tipo de dato que podrá contener el <code>vector</code>, en este caso el tipo es entero <code>int</code>.</p><h3 id="c-mo-inicializar-un-vector-con-un-arreglo"><strong>Cómo inicializar un vector con un arreglo</strong></h3><p>Esta vez, inicializaremos el vector con los valores contenidos en un arreglo creado con anterioridad, para esto, utilizaremos dos métodos de la clase vector: <strong><code>begin()</code></strong> y <strong><code>end()</code></strong>.</p><p>Veamos como es que estos métodos funcionan:</p><pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int main() {
    //Creamos el arreglo que contiene los datos que luego asignaremos al vector
    int miArreglo[] = { 5, 10, 15 };
    //Definimos el vector miVector y, mediante los metodos begin() y end() asignamos el contenido del arreglo que definimos con anterioridad
    vector&lt;int&gt; miVector(begin(miArreglo), end(miArreglo));


	for (int x : miVector)
		cout &lt;&lt; x &lt;&lt; " ";
		// 5 10 15 
}
</code></pre><p>Así como utilizamos un arreglo para generar un vector, podemos utilizar los dos métodos vistos en el ejemplo para copiar los valores de un vector hacia otro.</p><h3 id="vectores-de-tama-o-est-tico-como-inicializar-un-vector-especificando-el-tama-o-y-el-valor-contenido"><strong>Vectores de tamaño estático: Como inicializar un vector, especificando el tamaño y el valor contenido</strong></h3><p>Podemos especificar el tamaño y la información que contendrá el vector al momento de declararlo. Esto nos permitirá que el vector tenga un tamaño y un valor específico a través de la ejecución del código.</p><p>Aquí te muestro un ejemplo:</p><pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int main() {

  int cantidad_de_elementos = 5; 
  
  vector&lt;int&gt; miVectorFijo(cantidad_de_elementos, 2); 
  
  	for (int x : miVectorFijo)
		cout &lt;&lt; x &lt;&lt; " ";
// 		2 2 2 2 2 
}</code></pre><p>En el ejemplo, primero definimos una variable <code>cantidad_de_elementos = 5</code>, el cual especifica la cantidad de elementos máximos que contendrá el vector.</p><p>Luego, declaramos el vector <code>miVectorFijo</code><strong> </strong>pasándole 2 parámetros: el primero corresponde al número máximo de elementos que el vector contendrá, mientras que el segundo corresponde al valor que contendrá el vector.</p><p>Finalmente, iteramos con un bucle for para poder imprimir en pantalla el contenido del vector, por lo que nos imprimirá 5 veces 2.</p><h3 id="c-mo-inicializar-un-vector-usando-el-constructor-de-una-clase"><strong>Cómo inicializar un vector usando el constructor de una &nbsp;clase</strong></h3><p>Podemos inicializar vectores en constructores de clases, de esta forma podemos hacer que la clase sea más dinámica y, no tengamos que programar manualmente los valores del vector al inicializar la clase.</p><p>Veamos un ejemplo:</p><pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

class Vector {
	vector&lt;int&gt; miVector;

public:
	Vector(vector&lt;int&gt; newVector) {
	    miVector = newVector;
	}
	
	void imprimirVector() {
		for (int i = 0; i &lt; miVector.size(); i++)
			cout &lt;&lt; miVector[i] &lt;&lt; " ";
	}
	
};

int main() {

    vector &lt;int&gt; vectorNuevo;
    
	vectorNuevo.push_back(5);
	vectorNuevo.push_back(10);
	vectorNuevo.push_back(15);
	
	Vector vector(vectorNuevo);
	vector.imprimirVector();
	// 5 10 15 
}
</code></pre><p>Vamos a analizar el ejemplo:</p><pre><code class="language-C++">class Vector {
	vector&lt;int&gt; miVector;

public:
	Vector(vector&lt;int&gt; newVector) {
	    miVector = newVector;
	}
	
	void imprimirVector() {
		for (int i = 0; i &lt; miVector.size(); i++)
			cout &lt;&lt; miVector[i] &lt;&lt; " ";
	}
	
};</code></pre><p>Primero, creamos la clase <strong>Vector</strong>, luego creamos una variable de tipo vector a la cual llamamos <code>miVector</code>.</p><p>Luego, definimos el constructor de la clase, el cual tiene dos métodos: uno que toma el vector inicializado y otro que imprime en pantalla los valores contenidos en el vector.</p><pre><code class="language-C++">int main() {
    vector &lt;int&gt; vectorNuevo;
    
	vectorNuevo.push_back(5);
	vectorNuevo.push_back(10);
	vectorNuevo.push_back(15);
	
	Vector vector(vectorNuevo);
	vector.imprimirVector();
	// 5 10 15 
}</code></pre><p>Luego, en el bloque <code>main</code>, creamos un nuevo vector, le insertamos los valores 5,10 y 15.</p><p>Finalmente, imprimimos por pantalla el contenido del vector con el método <code>imprimirVector()</code>, el cual fue definido en la clase que creamos anteriormente.</p><p>Lo interesante del ejemplo, es que los métodos fueron definidos en la clase, por lo que, no debemos preocuparnos del tamaño del vector (el cual es obtenido por la clase).</p><h2 id="conclusiones"><strong>Conclusiones</strong></h2><p>En este artículo, hablamos sobre los vectores en C++, comenzamos diferenciando los arreglos de los vectores <em><strong>(recuerde, que los arreglos tienen un tamaño estático, mientras que los vectores tienen un tamaño dinámico, aunque, en caso de que sea necesario ese tamaño puede ser definido para que también sea estático).</strong></em></p><p>Luego, trabajamos con algunos métodos que podemos utilizar para inicializar el vector y mostramos ejemplos de cada método <em><strong>(nuevamente, recuerde que no es lo mismo declarar que inicializar, declarar es crear en memoria el vector, e inicializar es asignarle valores a ese vector).</strong></em></p><p>¡Que tengas un gran día programando <em><strong>(y aprendiendo)</strong></em>!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo usar GitHub Copilot para convertirte en un desarrollador más feliz y más productivo. ]]>
                </title>
                <description>
                    <![CDATA[ Hay una gran cantidad de herramientas de inteligencia artificial (IA) para desarrolladores en el mercado, pero para mi GitHub Copilot se diferencia del resto por su usabilidad, integración limpia al IDE y la palpable diferencia en la productividad al utilizarlo. Copilot ofrece una variedad de herramientas de Inteligencia Artificial que ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-usar-github-copilot-para-convertirse-en-un-desarrollador-mas-feliz-y-mas-productivo/</link>
                <guid isPermaLink="false">65fc110324402003fe4e4c0a</guid>
                
                    <category>
                        <![CDATA[ inteligencia artificial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lucas Agustín Morales Romero ]]>
                </dc:creator>
                <pubDate>Fri, 29 Mar 2024 00:44:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2024/03/Screenshot-2023-06-14-at-12.42.04-PM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/developer-productivity-with-github-copilot/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Use GitHub Copilot to Become a Happier and More Productive Developer</a>
      </p><p>Hay una gran cantidad de herramientas de inteligencia artificial (IA) para desarrolladores en el mercado, pero para mi GitHub Copilot se diferencia del resto por su usabilidad, integración limpia al IDE y la palpable diferencia en la productividad al utilizarlo.</p><p>Copilot ofrece una variedad de herramientas de Inteligencia Artificial que han simplificado radicalmente mi experiencia como desarrollador. Lo usé para generar código, pruebas e incluso aplicaciones simples. También es genial para depurar, refactorizar y documentar código existente.</p><p>Curiosamente, usar Copilot causo que desarrolle funciones más rápido de lo que las partes interesadas del negocio pueden revisarlas.</p><p>Es importante remarcar que, las herramientas de Inteligencia Artificial, incluido Copilot pueden estar superequivocadas, disculparse (o no) cuando las corregimos y, luego con total confianza, producir el mismo error.</p><p>Pero, siempre que estés atento a los puntos débiles de las herramientas de Inteligencia Artificial, y, tengas suficientes conocimientos para reconocer cuando se equivocan, vas a poder mitigarlos en el camino hacia una <a href="https://dev.to/github/github-copilot-un-ano-revolucionando-la-ia-466b">productividad sustancialmente mejorada</a>.</p><h2 id="como-configurar-github-copilot"><strong><strong>Como configurar GitHub Copilot</strong></strong></h2><p>Para configurar y ver el uso básico de Copilot, te recomiendo que consultes la <a href="https://docs.github.com/es/copilot">documentación oficial (en español)</a>. Puedes agregar Copilot a una cuenta personal o comercial, hay una prueba gratuita y, tiene un precio razonable luego del periodo de prueba.</p><p>Después de agregar Copilot a tu cuenta de GitHub, querrás instalar los plugins a tu IDE y logguearte para empezar a utilizarlo.</p><p>En este artículo, vamos a utilizar estas <a href="https://marketplace.visualstudio.com/search?term=copilot&amp;target=VSCode&amp;category=All%20categories&amp;sortBy=Relevance">extensiones de Visual Studio Code:</a></p><!--kg-card-begin: html--><table class="tableizer-table" style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-variant-alternates: inherit; font-variant-position: inherit; font-weight: 400; font-stretch: inherit; line-height: inherit; font-family: Arial, Helvetica, sans-serif; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px auto; padding: 0px; vertical-align: top; border-collapse: collapse; border-spacing: 0px; grid-column: main-start / main-end; background: radial-gradient(at left center, rgba(0, 0, 0, 0.2) 0px, transparent 75%) 0px center / 10px 100% no-repeat scroll, radial-gradient(at right center, rgba(0, 0, 0, 0.2) 0px, transparent 75%) 100% center / 10px 100% scroll rgb(255, 255, 255); display: inline-block; max-width: 100%; overflow-x: auto; white-space: normal; width: auto; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; color: rgb(28, 28, 28); text-align: center;"><thead style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><tr class="tableizer-firstrow" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><th style="box-sizing: inherit; border: 1px solid rgb(226, 236, 243); font-style: inherit; font-variant: inherit; font-weight: bold; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 1.2rem; margin: 0px; padding: 6px 12px; vertical-align: baseline; background-color: rgb(16, 78, 139); color: rgb(255, 255, 255); letter-spacing: 0.2px; text-align: left; text-transform: uppercase;">EXTENSION</th><th style="box-sizing: inherit; border: 1px solid rgb(226, 236, 243); font-style: inherit; font-variant: inherit; font-weight: bold; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 1.2rem; margin: 0px; padding: 6px 12px; vertical-align: baseline; background-color: rgb(16, 78, 139); color: rgb(255, 255, 255); letter-spacing: 0.2px; text-align: left; text-transform: uppercase;">DESCRIPCION</th></tr></thead><tbody style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;"><a href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilot" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline; background-color: transparent; color: var(--ghost-accent-color); text-decoration: underline; word-break: break-word;">Copilot</a></td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Programador de pares potenciado por Inteligencia Artificial con sugerencias de codigo dentro del IDE</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;"><a href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline; background-color: transparent; color: var(--ghost-accent-color); text-decoration: underline; word-break: break-word;">Copilot Chat</a></td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Chat interactivo embebido en el IDE</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;"><a href="https://marketplace.visualstudio.com/items?itemName=GitHub.heygithub" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline; background-color: transparent; color: var(--ghost-accent-color); text-decoration: underline; word-break: break-word;">Copilot Voice</a></td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Asistente de voz (permite programar utilizando tu voz)</td></tr></tbody></table><!--kg-card-end: html--><p>Notas:</p><ol><li>Esta información está actualizada al momento de escribir este artículo, pero probablemente cambie a medida que GitHub avance en el desarrollo de sus productos.</li><li>Todavía no recibí acceso a Copilot Voice, por lo que mi perspectiva está limitada y basada en la documentación ofrecida por GitHub.</li></ol><h3 id="privacidad"><strong>Privacidad</strong></h3><p>Antes de sumergirnos en algunos casos de uso de Copilot, una aclaración rápida en cuanto a la privacidad: Básicamente, si confías en GitHub para alojar tu código fuente, puedes confiar en lo que harán con los prompts que envíes a Copilot y tus fragmentos de código. [Por favor, revisa las <a href="https://github.com/features/copilot#faq">preguntas frecuentes (en inglés)</a> y la <a href="https://docs.github.com/es/site-policy/privacy-policies/github-general-privacy-statement">declaración de privacidad</a>]</p><h3></h3><h2 id="casos-de-uso-para-github-copilot"><strong><strong><strong><strong><strong>Casos de uso para GitHub Copilot</strong></strong></strong></strong></strong></h2><p>Los casos de uso de GitHub Copilot son numerosos, y pueden realmente agilizar el proceso de desarrollo.</p><p>A continuación, te dejo una lista de lo que puedes hacer con las extensiones de Copilot:</p><!--kg-card-begin: html--><table class="tableizer-table" style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-variant-alternates: inherit; font-variant-position: inherit; font-weight: 400; font-stretch: inherit; line-height: inherit; font-family: Arial, Helvetica, sans-serif; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px auto; padding: 0px; vertical-align: top; border-collapse: collapse; border-spacing: 0px; grid-column: main-start / main-end; background: radial-gradient(at left center, rgba(0, 0, 0, 0.2) 0px, transparent 75%) 0px center / 10px 100% no-repeat scroll, radial-gradient(at right center, rgba(0, 0, 0, 0.2) 0px, transparent 75%) 100% center / 10px 100% scroll rgb(255, 255, 255); display: inline-block; max-width: 100%; overflow-x: auto; white-space: normal; width: auto; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; color: rgb(28, 28, 28); text-align: center;"><thead style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><tr class="tableizer-firstrow" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><th style="box-sizing: inherit; border: 1px solid rgb(226, 236, 243); font-style: inherit; font-variant: inherit; font-weight: bold; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 1.2rem; margin: 0px; padding: 6px 12px; vertical-align: baseline; background-color: rgb(16, 78, 139); color: rgb(255, 255, 255); letter-spacing: 0.2px; text-align: left; text-transform: uppercase;">CATEGORIA</th><th style="box-sizing: inherit; border: 1px solid rgb(226, 236, 243); font-style: inherit; font-variant: inherit; font-weight: bold; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 1.2rem; margin: 0px; padding: 6px 12px; vertical-align: baseline; background-color: rgb(16, 78, 139); color: rgb(255, 255, 255); letter-spacing: 0.2px; text-align: left; text-transform: uppercase;">EXTENSION(ES)</th></tr></thead><tbody style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Generacion de codigo</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot, Copilot Voice</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Explicacion del codigo</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot Chat, Copilot Voice</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Traduccion de lenguaje</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot Chat</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Depurar</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot Chat</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Refactorizar</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot Chat</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Creacion de pruebas</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot, Copilot Chat</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Revision de codigo</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot Chat</td></tr><tr style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(90deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Desarrollo guiado por voz</td><td style="box-sizing: inherit; border: 1px solid rgb(204, 204, 204); font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 12px; margin: 3px; padding: 4px; vertical-align: baseline; background-image: linear-gradient(270deg, rgb(255, 255, 255) 50%, rgba(255, 255, 255, 0)); background-position: 100% 0px; background-repeat: no-repeat; background-size: 20px 100%; text-align: left;">Copilot Voice</td></tr></tbody></table><!--kg-card-end: html--><h3 id="generaci-n-de-c-digo">Generación de código</h3><p>Copilot es conocido por su capacidad para finalizar el código. Si escribís un comentario o si escribís el principio de una línea de código, Copilot te sugerirá una solución que puedes aceptar, ignorar o, incluso explorar alternativas. Esta característica es conocida como "texto fantasma".</p><p>Una vez que instalada la extensión de Copilot e iniciada la sesión, utilizarlo es tan sencillo como tipear instrucciones y pulsar la tecla Tabulador a medida que van surgiendo las sugerencias.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/03/copilot_completar2.gif" class="kg-image" alt="copilot_completar2" width="724" height="170" loading="lazy"><figcaption>Un comentario en Ruby que Copilot uso para crear un método.</figcaption></figure><p>Llevando un poco más allá la función de completar, Copilot puede tomar un prompt y usarlo para construir toda una aplicación.</p><p>Le pedí que creara una API REST en Node con funciones ABM para "productos", y género código funcional. Esto es impresionante; &nbsp;inclusive le di el mismo prompt a ChatGPT, que también me dio instrucciones de como realizar el proyecto, lo cuan es también impresionante. </p><p>Copilot Voice puede tanto escribir como editar código basado en comandos de voz, la mayoría de las veces es más rápido utilizar Copilot con el teclado que dictando una a una las líneas de código usando Voice, pero es totalmente factible utilizar Voice para crear y ejecutar código sin necesidad de utilizar el teclado, algo mucho más que útil para personas que posean alguna dificultad para usar el teclado.</p><h3 id="explicaci-n-de-c-digo"><strong>Explicación de código</strong></h3><p>A menudo debí sentarme frente a la PC para intentar deducir que es lo que un boque de código está haciendo. Algunas veces es <a href="https://es.wikipedia.org/wiki/C%C3%B3digo_heredado">código heredado (Legacy Code)</a> del cual no entiendo el contexto del negocio, o a veces está usando una librería particular que nunca use, a veces también debo reconocer que maldije a la persona que lo escribió, incluso si esa persona fui yo.</p><p>A continuación te muestro el código generado por Copilot con el prompt que utilice antes "Un API REST en Node...":</p><pre><code class="language-javascript">app.get('/products/:id', (req, res) =&gt; {
  const id = req.params.id;
  const product = products.find((p) =&gt; p.id === id);
  if (product) {
    res.json(product);
  } else {
    res.status(404).json({ error: 'El producto no fue encontrado' });
  }
});</code></pre><p>Tome el código y se lo di como entrada a Copilot para que me explicara el código, esta fue su respuesta:</p><p><em>Aquí está la explicación del código<em>:</em></em></p><ol><li><em>Definimos la ruta con la ruta /productos/:id. Los dos puntos : en la ruta indica que es un parámetro de la ruta.<em> </em>El valor del parámetro de la ruta estará disponible en req.params, por ejemplo, si la ruta es /products/:id y hacemos una solicitud a /products/5, entonces el valor de req.params será { id: 5}.</em></li><li><em>Obtenemos el id de req.params y buscamos el producto con el id que obtuvimos del arreglo de productos. Si existe el producto lo mostramos, si no existe devolvemos un código de error 404 con el mensaje "El producto no fue encontrado".</em></li></ol><p>Este es un segmento de código sencillo, y la respuesta brindada por Copilot es clara y directa, sería bastante útil agregar esto como un comentario sobre el código de la función.</p><p>Otro buen ejemplo de uso son las expresiones regulares, entiendo como funcionan, pero a veces no tengo la paciencia para entender que es lo que la expresión regular esta haciendo. Le di como entrada a Copilot esté gigantesca expresión regular para la validación de un correo electrónico:</p><pre><code>(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])</code></pre><p>Explico la expresión regular a un alto nivel, indicando que está dividido en la parte local y el dominio, representado antes y después del símbolo "@" en una dirección de correo electrónico. Luego, describió los caracteres permitidos en cada parte, bastante útil.</p><h3 id="traducir-c-digo-entre-lenguajes-"><strong>Traducir código (entre lenguajes)</strong></h3><p>A menudo se requiere que los desarrolladores aprendamos rápidamente nuevos lenguajes y frameworks, Copilot Chat hace esta tarea bastante sencilla, aquí te muestro un arreglo de productos en JavaScript que fue convertido a Ruby por Copilot:</p><pre><code class="language-javascript">let productos = [
  { id: '1', descripcion: 'Producto 1', precio: 10.99 },
  { id: '2', descripcion: 'Producto 2', precio: 19.99 },
  { id: '3', descripcion: 'Producto 3', precio: 7.99 }
];</code></pre><pre><code class="language-ruby">productos = [
  { id: '1', descripcion: 'Producto 1', precio: 10.99 },
  { id: '2', descripcion: 'Producto 2', precio: 19.99 },
  { id: '3', descripcion: 'Producto 3', precio: 7.99 }
]</code></pre><p>Este es un ejemplo muy sencillo, así que transformemos esto en una clase y vallamos en sentido contrario (de Ruby a JavaScript):</p><pre><code class="language-ruby">class Producto
  attr_reader :nombre, :precio

  def initialize(nombre, precio)
    @nombre = nombre
    @precio = precio
  end
end</code></pre><pre><code class="language-javascript">class Producto {
  constructor(nombre, precio) {
    this.nombre = nombre;
    this.precio = precio;
  }
}</code></pre><p>Esto funciono de maravilla, inclusive le pedí que lo transformara en TypeScript y funciono perfecto:</p><pre><code class="language-typescript">class Producto {
  nombre: string;
  precio: number;

  constructor(nombre: string, precio: number) {
    this.nombre = nombre;
    this.precio = precio;
  }
}</code></pre><h3 id="depurando-c-digo"><strong>Depurando código</strong></h3><p>Esta es una de las funciones más útiles que posee Copilot Chat, puedes darle un fragmento de código problemático o el mensaje de error que tienes y el programa te indicara cuál "piensa" que es el error</p><p>No recuerdo la cantidad de veces que me arranque los pelos tratando de encontrar un error de sintaxis, la habilidad de Copilot para arreglar errores me hacen más feliz (y me permite conservar mi cabello).</p><p>También puedes darle como entrada a Copilot Chat un mensaje de error sin ningún otro prompt y te devolverá el problema que lo ocasiona, en este caso intencionalmente removí un punto del código de la API &nbsp;REST en Node:</p><pre><code class="language-javascript">products[productIndex] = { id, ..req.body };</code></pre><p>He copiado/pegado el mensaje de error en el Chat, y me ha respondido con...</p><blockquote><code>req.body</code></blockquote><p>Esto es correcto (la linea y la fuente del error) e incorrecto (ya que debería ser solo un punto). Luego, me dio un fragmento de código con tres puntos, el cual es también correcto.</p><p>Como te mencione al principio, siempre debes chequear el trabajo de las herramientas de IA, aun así estoy impresionado con la habilidad de Copilot de tomar un error, describir lo que "piensa" que está mal y, luego sugerir la corrección.</p><h3 id="refactorizaci-n"><strong>Refactorización</strong></h3><p>Otro gran caso de uso es la refactorización, consideremos el siguiente código:</p><blockquote><code>req.body</code></blockquote><p>Esto es correcto (la linea y la fuente del error) e incorrecto (ya que debería ser solo un punto). Luego, me dio un fragmento de código con tres puntos, el cual es también correcto.</p><p>Como te mencione al principio, siempre debes chequear el trabajo de las herramientas de IA, aun así estoy impresionado con la habilidad de Copilot de tomar un error, describir lo que "piensa" que está mal y, luego sugerir la corrección.</p><h3 id="refactorizaci-n-1"><strong>Refactorización</strong></h3><p>Otro gran caso de uso es la refactorización, consideremos el siguiente código:</p><pre><code class="language-ruby">def precio_con_descuento
  precio - (precio * tasa_de_descuento)
end</code></pre><p>Este codigo para calcular descuentos no realiza verificaciones para validar que no le demos valores nulos, cadenas de texto que deberían ser números o valores razonables para &nbsp;"precio" o "tasa_de_descuento", necesitamos que el código haga lo siguiente: &nbsp;</p><ol><li>Asegurarse que "precio" sea un Integer o Float (no nulo)</li><li>Asegurarse que "precio" no sea negativo</li><li>Asegurarse que "tasa_de_descuento" sea un Float (no nulo)</li><li>Asegurarse que "tasa_de_descuento" no sea negativo y menor o igual que 1</li></ol><p>Copilot Chat puede manejar esto fácilmente...</p><pre><code class="language-ruby">def precio_con_descuento
  raise ArgumentError, "El precio debe ser un número positivo" unless precio.is_a?(Numeric) &amp;&amp; precio &gt;= 0
  raise ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1" unless tasa_de_descuento.is_a?(Numeric) &amp;&amp; tasa_de_descuento &gt;= 0 &amp;&amp; tasa_de_descuento &lt;= 1

  precio - (precio * tasa_de_descuento)
end</code></pre><h3 id="generaci-n-de-pruebas"><strong>Generación de pruebas</strong></h3><p>Estrictamente hablando, la generación de pruebas es una subsección de la "Generación de código", pero es tan útil, que sentí que merecía su propia sección.</p><p>Generar pruebas unitarias para el código puede ser tedioso si estás tratando de cubrir caminos felices y tristes, casos principales de uso y casos extremos. Nuestra función de "precio_con_descuento" necesita casos de prueba para asegurarnos que se genere un aviso de error si "precio" o "tasa_de_descuento" no cumplen con los requisitos. Además, queremos probar lo siguiente:</p><ol><li>Un "precio" sin una "tasa_de_descuento"</li><li>Un "precio" con una "tasa_de_descuento" razonable (por ejemplo, un 10% de descuento)</li><li>Un "precio" con un 100% de "tasa_de_descuento" (por ejemplo, si queremos regalar el producto)</li></ol><p>Con estos y nuestros casos de error anteriores, esto es lo que Copilot Chat genero, despues de alguno pequeños ajustes (re-prompting) y cambiando de Minitest a Rspec: </p><pre><code class="language-ruby">RSpec.describe Producto do
  describe "#precio_con_descuento" do
    context "cuando se proporciona un precio válido y una tasa de descuento" do
      it "retorna el precio con el descuento aplicado" do
        producto = Producto.new("Producto de Prueba", 100, 0.2)
        expect(producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento)).to eq(80)
      end
    end

    context "cuando se proporciona un precio nulo" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", nil, 0.2)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "El precio debe ser un número positivo")
      end
    end

    context "cuando se proporciona un precio menor que 0" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", -100, 0.2)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "El precio debe ser un número positivo")
      end
    end

    context "cuando se proporciona una tasa de descuento nula" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", 100, nil)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1")
      end
    end

    context "cuando se proporciona una tasa de descuento menor que 0" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", 100, -0.2)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1")
      end
    end

    context "cuando se proporciona una tasa de descuento mayor que 1" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", 100, 1.5)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1")
      end
    end
  end
end</code></pre><p>Una prueba para entradas válidas, cinco para entradas incorrectas, los seis funcionan, ¡y yo no tuve que escribirlos!</p><h3 id="revisi-n-de-c-digo"><strong>Revisión de código</strong></h3><p>Una de las características destacables de Github Copilot es la <a href="https://docs.github.com/es/copilot/github-copilot-enterprise/copilot-pull-request-summaries/about-copilot-pull-request-summaries">elaboración de los resúmenes de solicitudes de incorporación de cambios de Copilot</a>. cabe destacar que <strong>esta función está solo disponible para quienes posean una suscripción de Github Copilot Enterprise</strong>, aquí te presento algunos puntos clave:</p><ul><li><strong>Generación automática</strong> – Deje que Copilot complete la plantilla de Pull Request o explique el código.</li><li><strong>Generación de pruebas</strong> – Genera pruebas para el código basado en el análisis de Copilot</li><li><strong>Texto fantasma</strong> – Reciba sugerencias mientras escribe el Pull Request</li></ul><h3 id="desarrollo-guiada-por-voz"><strong>Desarrollo guiada por voz</strong></h3><p>¡Antes conocida como "Hey, Github!", Copilot Voice te permite utilizar la voz para generar los prompts para interactuar con el código, Voice cuenta con estas impresionantes capacidades:</p><ul><li><strong>Escribir/Editar código</strong> – Usa comandos de voz para disparar sugerencias de código de Copilot</li><li><strong>Explora el código </strong> – Recorre un archivo sin utilizar el mouse o el teclado</li><li><strong><strong>Control</strong>a el<strong> IDE</strong></strong> – Dispare cualquier comando de Visual Studio Code utilizando su voz</li><li><strong>Resumen del código</strong> – Obtenga resúmenes de bloques de código</li></ul><h2 id="resumen"><strong>Resumen</strong></h2><p>GitHub rápidamente está generando una explosión de productividad con toda la familia de addons Copilot. Está incrementando el tiempo que disfruto programando y reduciendo el que antes gastaba en tareas triviales. Lo animo, querido lector, a seguir de cerca los avances de Copilot, porque se producen rápidamente.</p><p>Ignora los artículos sensacionalistas que prometen "un aumento de productividad de 10 veces la que tiene ahora", pero no ignores esta investigación acerca del <a href="https://github-blog.translate.goog/2022-09-07-research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/?_x_tr_sl=en&amp;_x_tr_tl=es&amp;_x_tr_hl=es&amp;_x_tr_pto=wapp">impacto que Copilot tiene en la productividad y felicidad de los programadores</a>.</p><p>Dedique un poco de su tiempo a utilizar las herramientas que Copilot le brinda, póngalo a prueba en su día a día, y, le garantizo que quedará encantado por el efecto que genera en su productividad y felicidad.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
