CursosEmpresasBlogLiveConfPrecios

Crear Formulario de Login

Clase 16 de 29 • Curso de React Router 5 y Redux

Clase anteriorSiguiente clase

Contenido del curso

Bienvenida al curso

  • 1
    Todo lo que aprenderás sobre React Router y Redux

    Todo lo que aprenderás sobre React Router y Redux

    01:30 min

¿Qué es React Router? y Aplicarlo en tus proyectos

  • 2
    ¿Qué es React Router y cómo instalarlo?

    ¿Qué es React Router y cómo instalarlo?

    02:54 min
  • 3
    Crear nuestro archivo de Rutas

    Crear nuestro archivo de Rutas

    07:33 min
  • 4
    Container: Login

    Container: Login

    10:29 min
  • 5
    Container: Register

    Container: Register

    06:28 min
  • 6
    Container: 404 Not Found

    Container: 404 Not Found

    06:43 min
  • 7
    Componente: Layout

    Componente: Layout

    05:10 min
  • 8
    Manejando enlaces y configuraciones

    Manejando enlaces y configuraciones

    06:33 min

¿Qué es Redux?

  • 9
    Qué es Redux

    Qué es Redux

    02:17 min
  • 10

    ¿Qué es Redux? Profundizando en la herramienta

    01:32 min
  • 11
    Instalación de Redux

    Instalación de Redux

    04:40 min
  • 12
    Creando el Store de Redux

    Creando el Store de Redux

    12:53 min

Aplicando Redux a nuestra aplicación

  • 13
    Creando los reducers

    Creando los reducers

    10:40 min
  • 14
    Finalizando reducers y eliminar favoritos

    Finalizando reducers y eliminar favoritos

    08:26 min
  • 15
    Debuggeando nuestro proyecto (agregando validaciones a nuestro componente card)

    Debuggeando nuestro proyecto (agregando validaciones a nuestro componente card)

    04:19 min
  • 16
    Crear Formulario de Login

    Crear Formulario de Login

    Viendo ahora
  • 17
    Formulario de Login con Redux

    Formulario de Login con Redux

    06:28 min
  • 18
    Creando un Servicio para Gravatar

    Creando un Servicio para Gravatar

    05:28 min
  • 19
    Uso de gravatar en nuestro proyecto

    Uso de gravatar en nuestro proyecto

    07:16 min
  • 20
    Validación para LogIn LogOut

    Validación para LogIn LogOut

    09:15 min
  • 21
    Register

    Register

    07:00 min
  • 22
    Register con Redux

    Register con Redux

    04:17 min
  • 23
    Vista general del player

    Vista general del player

    05:26 min
  • 24
    Arreglando la funcionalidad del player

    Arreglando la funcionalidad del player

    06:55 min
  • 25
    Terminando de detallar nuestro player

    Terminando de detallar nuestro player

    13:50 min
  • 26
    Validaciones

    Validaciones

    10:35 min
  • 27
    Validaciones de UI

    Validaciones de UI

    07:04 min
  • 28
    Debug con Redux Devtools

    Debug con Redux Devtools

    05:57 min

Cierre del curso

  • 29
    Cierre del Proyecto

    Cierre del Proyecto

    00:39 min
  • Tomar el examen del curso
    • David Behar

      David Behar

      student•
      hace 6 años

      Tengan en cuenta que su botón tiene que ser de tipo submit para que funcione.

        Jesús Miguel Quinto Teran

        Jesús Miguel Quinto Teran

        student•
        hace 6 años

        En realidad no tuve que agregar el tipo submit sobre el botón, lo cual es algo curioso.

        rusbel bermúdez rivera

        rusbel bermúdez rivera

        student•
        hace 6 años

        En mi caso agregue el type=submit al botón para que hiciera lo propio.

      Seba Cardoso

      Seba Cardoso

      student•
      hace 6 años

      En esta clase de React con Richard se explica como se agregan los valores dinamicos del formulario. Minuto 4:00. Clase de React

        silvana murgo

        silvana murgo

        student•
        hace 5 años

        Gracias :D

      Salvador Galliano

      Salvador Galliano

      student•
      hace 5 años

      Otra forma de hacerlo es usando useReducer de React Hooks. Dejo mi codigo y el resultado.

      useReducer.png
      useReducer2.png

        Andrés Felipe Eslava Zuluaga

        Andrés Felipe Eslava Zuluaga

        student•
        hace 5 años

        Esta forma se ve excelente! No sabía el uso de useReduce. Investigaré sobre este hook

        William Rodriguez

        William Rodriguez

        student•
        hace 5 años

        Interesante tu implementación se ve limpia con useReducer.

      Andrés Campuzano Garzón

      Andrés Campuzano Garzón

      student•
      hace 6 años

      🦄 Acá el código de lo realizado hasta el momento: https://github.com/AndresCampuzano/React-Router-and-Redux/commit/381a70e544dd29de467e57416d1d3822f33ed632

      Marco Antonio Macedo Preciado

      Marco Antonio Macedo Preciado

      student•
      hace 6 años

      ¿Qué significan los "[]" en [event.target.name]? ¿Cuál es su función?

        Alexis Alberto Texis Auza

        Alexis Alberto Texis Auza

        student•
        hace 6 años

        Hola marco,el uso de corchetes se utiliza para poder aplicarle el valor de una variable a un key dentro de un objeto. De lo contrario estarías asignándole o en este caso buscando un atributo(key) con el nombre event.target.value.

        En este caso necesitamos el valor del atributo name del tag input correspondiente. Salida : e.target.name-> 'email' o 'password' De esta forma podremos hacer referencia a que key modificar en el estado

      Armando de jesus santiz lopez

      Armando de jesus santiz lopez

      student•
      hace 6 años

      Es buen práctica mezclar estados locales con Redux ?

        Daniel Alberto Esquinazi

        Daniel Alberto Esquinazi

        student•
        hace 6 años

        En mi opinión deberías usar Redux solamente cuando sea necesario, entonces si tenes el state de un componente que no necesita ser global como el caso del estado del formulario es mejor utilizar el manejo de estado nativo de React y no con Redux.

      Sebastián Buitrago

      Sebastián Buitrago

      student•
      hace 5 años

      Si usan prettier agreguen esta linea a su config para que él quite los parentesis cuando solo haya un parametro

      "prettier.arrowParens": "avoid",
      Orlando Manuel Mendoza Vargas

      Orlando Manuel Mendoza Vargas

      student•
      hace 5 años

      Reto completado, aquí está mi UI mejorada del Login y de Register 💚💚💚 .

      2021-04-05 (4).png
      .
      2021-04-05 (5).png

      Jonh Pertuz pertuz

      Jonh Pertuz pertuz

      student•
      hace 4 años

      En que curso enseñan el tema de login y como manejar y mantener el inicio de sesion ?

        Héctor Eduardo López Carballo

        Héctor Eduardo López Carballo

        student•
        hace 4 años

        Hola!

        Podrías echarle un ojo al Curso de Backend con Node.js

      Abraham Serrano Montiel

      Abraham Serrano Montiel

      student•
      hace 6 años

      Una duda, ¿Por que se pone event.target ?

        Gabriel De Andrade

        Gabriel De Andrade

        student•
        hace 6 años

        El event.target hace referencia al Elemento que llamó al evento, de esta manera podemos por ejemplo obtener el valor de ese Elemento :D

        Luis Alberto Ruiz Sarmiento

        Luis Alberto Ruiz Sarmiento

        student•
        hace 6 años

        Debes tener en cuenta que no siempre lo vas a encontrar así, hay ocaciones que lo veras de la siguiente forma:

        handleInput={(e) => e.target}

        La e es una variable y la puedes nombrar a tu gusto, solo que habitualmente se maneja con event o e

      Manuel Rivera

      Manuel Rivera

      student•
      hace 6 años

      en las devtools podemos observar los props que tiene cada componente, es una ayuda muy grande para debuggear también

      Javier Fuentes Mora

      Javier Fuentes Mora

      teacher•
      hace 6 años

      Tambien pueden usar react-redux-form les ayuda . amanejar los estados y les ayud a aimplementar validaciones

      Andrés Felipe Eslava Zuluaga

      Andrés Felipe Eslava Zuluaga

      student•
      hace 5 años

      Login.jsx

      import React, { useState } from 'react'; import { Link } from 'react-router-dom'; import googleIcon from '../assets/img/google-icon.png'; import twitterIcon from '../assets/img/twitter-icon.png'; import '../assets/styles/containers/Login.scss'; const Login = () => { const [formValues, setFormValues] = useState({ email: '', password: '', }); const handleInput = (event) => { setFormValues({ ...formValues, [event.target.name]: event.target.value, }); }; const handleSubmit = (event) => { event.preventDefault(); console.log('formValues', formValues); }; return ( <section className='Login'> <section className='Login__container'> <h3>Inicia sesión</h3> <form className='Login__container--form' action='' onSubmit={handleSubmit} > <input className='input' type='text' name='email' id='email' placeholder='Correo' onChange={handleInput} /> <input className='input' type='password' name='password' id='password' placeholder='Contraseña' onChange={handleInput} /> <button className='button' type='submit'>Iniciar sesión</button> <div className='Login__container--remember-me'> <label htmlFor='cbox1'> <input type='checkbox' name='cbox1' id='cbox1' value='Checkbox' /> Recuérdame </label> <Link to='/forgot-password'> Olvidé mi contraseña </Link> </div> </form> <section className='Login__container--social-media'> <div> <img src={googleIcon} alt='Google' /> inicia sesión con Google </div> <div> <img src={twitterIcon} alt='Twitter' /> inicia sesión con Twitter </div> </section> <p className='Login__container--register'> No tienes ninguna cuenta? <Link to='/register'> Regístrate </Link> </p> </section> </section> ); }; export default Login;
      Juan Daniel Martínez Navarro

      Juan Daniel Martínez Navarro

      student•
      hace 5 años

      Para quien le sirva encontré la forma de cambiar el color del header según la ruta en la que te encuentres.

      Primero nos ubicamos en el componente Header para agregarle una propiedad y poder cambiarle el estilo "dinámicamente":

      const Header = ({ color }) => ( <header className={`header ${color}`} > ...

      Como ven le agregué la propiedad llamada color (No se me ocurrió un mejor nombre 🥴) que esta la vamos a agregar al className de <header>, dejando su clase original .header para no afectar la estructura ni posicionamiento.

      Luego nos dirijimos al componente Layout que es donde importamos el componente Header.

      Necesitamos importar useLocation de router DOM

      import { useLocation } from 'react-router-dom';

      Ahora como ya lo hemos hecho con muchos componentes, necesitamos adaptar nuestro componente Layout para agregar lógica.

      const Layout = ({ children }) => { const pathname = useLocation().pathname; //Obtenemos la ruta actual return ( <div className="App"> { pathname == '/login' | pathname == '/register' ? <Header color='header__login' /> : <Header /> } {children} <Footer /> </div> ); };

      En una constante pathname guardamos la ruta en la que nos encontremos actualmente al navegar en nuestra app por medio de useLocation().pathname.

      Lo siguiente que hicimos fue hacer un condicional, en caso de que la ruta actual sea /login o /register usamos la etiqueta de nuestro componente Header con el valor de color='header__login' la cual es la clase CSS la cual contendrá solamente el color verde.

      Agregamos dicha clase en Header.scss:

      .header__login { background-color: #21c08b; }

      Ya con esto les debería funcionar, prueben cambiando del Home al Login, Register y viceversa.

      Miguel Angel Ochoa Torres

      Miguel Angel Ochoa Torres

      student•
      hace 5 años

      trate de devolverme algunos videos para verlos de nuevo, pero aparecen al 100%. porfa que aparezca el avance pero que el video vuelva a iniciar de 0

        José Enrique Pérez Aquino

        José Enrique Pérez Aquino

        student•
        hace 5 años

        Puedes presionar 0 justo después de que carga el vídeo para regresarlo al principio

        Rafael Mujica

        Rafael Mujica

        student•
        hace 5 años

        Hola, yo desactive el autoplay (en el engranaje ) asi que cuando me regreso a algún video ya visto no me redirecciona al siguiente y luego si ubico el video al inicio o al punto que necesite. Saludos

      Steve Anthony Luzquiños Agama

      Steve Anthony Luzquiños Agama

      student•
      hace 4 años

      Hola, para hacer validaciones les sugiero usar los siguientes regex en el email y password:

      const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ const PASSWORD_REGEX = /^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[!"#\$%&'\(\)\*\+,-\.\/:;<=>\?@[\]\^_`\{\|}~])[a-zA-Z0-9!"#\$%&'\(\)\*\+,-\.\/:;<=>\?@[\]\^_`\{\|}~]{6,}$/

      El primero lo obtuve de aquí, el segundo de aquí.

      Para enviar al usuario un mensaje de éxito o fracaso puede usar SweetAlert2.

      Finalmente, les comparto mis validaciones

      const handleSubmit = e => { e.preventDefault() console.log(form) if (!EMAIL_REGEX.test(form.email)) return Swal.fire({ icon: 'error', title: 'Email inválido', text: 'Debes ingresar un email válido' }) if (!PASSWORD_REGEX.test(form.password)) return Swal.fire({ icon: 'error', title: 'Contraseña inválida', html: 'Debes ingresar una contraseña con:<br><br>' + '- 6 caracteres<br>' + '- Una minúsclia<br>' + '- Una mayúsclia<br>' + '- Un número<br>' + '- Un caracter especial<br>' }) return Swal.fire({ icon: 'success', title: 'Inicio de sesión exitoso', timer: 1500 }) }

      Happy coding!

      Beto Martinez

      Beto Martinez

      student•
      hace 6 años

      No entiendo como el setValues "setea" los valores Este codigo en especifico, lo desestructura el form y ¿Despues que?

      const handleInput = (event) => { setValues({ ...form, [event.target.name]: event.target.value, }); };```
        Christian Perez

        Christian Perez

        student•
        hace 6 años

        Hola! Recuerda que en hooks useState toma dos valores:

        const [form, setValues] = useState({ email: '' })

        Durante el renderizado inicial, el estado devuelto (form) es el mismo que el valor pasado como primer argumento ({email: " "}). Por la tanto comienza vacío.

        El segundo argumento es con el que actualizamos el estado.

        Cuando llamas a handleInput esta funcion destructura y toma el valor de form y en este caso crea un objeto dinámica mente el cual pasa a ser el nuevo estado

        { event.target.email: event.target.value; event.target.password: event.target.value }

        Aquí esta la documentación de hooks, por si le quieres dar una revisada. No me encanta leer jeje pero personalmente se me hizo super clara.

        David Antonio Garcia Saaib

        David Antonio Garcia Saaib

        student•
        hace 5 años

        A ok xD, de manera general lo que pasa ahi es que cada cambio que hagas al string del un input se guarda en automatico el ...form es para que guarde su valor anterior y la linea que sigue es para si hay algun cambio en alguno de los dos inputs lo guarde en su espacio correspondiente

        Todo eso esta en setValues que es una funcion que da valor a form.

        Ponlo asi, cada letra o borrado de letra se actualiza el valor de form, no del form html si no del form hook, o la variable form , o el objeto form que estamos declarando con JS y useState

      Mateo Buitrago

      Mateo Buitrago

      student•
      hace 6 años

      Una pregunta, por qué se utilizan los [] en [event.target.name]:event.target.value ?

        Cristian Fabian Tovar

        Cristian Fabian Tovar

        student•
        hace 6 años

        05:40 dice que es para obtener de forma dinámica la información, es decir que en esa línea puede estar alterando: event.target.email ó event.target.password Dependerá del input que se esté alterando en el momento, cualquier duda te invito a romper el código en esa sección y ver lo que pasa en la consola del navegador, es divertido y te ayuda a comprender por tí mismo lo que ocurre

        David Antonio Garcia Saaib

        David Antonio Garcia Saaib

        student•
        hace 5 años

        es como iterar en el target, en lugar de poner uno para email y uno para password que guarde el valor pone eso para que se guarde en el target.name correspontiene ya sea email, password u otro

      Jhonatan David Ibarra Lavado

      Jhonatan David Ibarra Lavado

      student•
      hace 6 años

      repasando la clase , estupendo

      Jorge Alberto Rodriguez Flores

      Jorge Alberto Rodriguez Flores

      student•
      hace 5 años

      Igual también podemos poner un objeto vació en nuestro useState y funcionara.

    Escuelas

    • Desarrollo Web
      • Fundamentos del Desarrollo Web Profesional
      • Diseño y Desarrollo Frontend
      • Desarrollo Frontend con JavaScript
      • Desarrollo Frontend con Vue.js
      • Desarrollo Frontend con Angular
      • Desarrollo Frontend con React.js
      • Desarrollo Backend con Node.js
      • Desarrollo Backend con Python
      • Desarrollo Backend con Java
      • Desarrollo Backend con PHP
      • Desarrollo Backend con Ruby
      • Bases de Datos para Web
      • Seguridad Web & API
      • Testing Automatizado y QA para Web
      • Arquitecturas Web Modernas y Escalabilidad
      • DevOps y Cloud para Desarrolladores Web
    • English Academy
      • Inglés Básico A1
      • Inglés Básico A2
      • Inglés Intermedio B1
      • Inglés Intermedio Alto B2
      • Inglés Avanzado C1
      • Inglés para Propósitos Específicos
      • Inglés de Negocios
    • Marketing Digital
      • Fundamentos de Marketing Digital
      • Marketing de Contenidos y Redacción Persuasiva
      • SEO y Posicionamiento Web
      • Social Media Marketing y Community Management
      • Publicidad Digital y Paid Media
      • Analítica Digital y Optimización (CRO)
      • Estrategia de Marketing y Growth
      • Marketing de Marca y Comunicación Estratégica
      • Marketing para E-commerce
      • Marketing B2B
      • Inteligencia Artificial Aplicada al Marketing
      • Automatización del Marketing
      • Marca Personal y Marketing Freelance
      • Ventas y Experiencia del Cliente
      • Creación de Contenido para Redes Sociales
    • Inteligencia Artificial y Data Science
      • Fundamentos de Data Science y AI
      • Análisis y Visualización de Datos
      • Machine Learning y Deep Learning
      • Data Engineer
      • Inteligencia Artificial para la Productividad
      • Desarrollo de Aplicaciones con IA
      • AI Software Engineer
    • Ciberseguridad
      • Fundamentos de Ciberseguridad
      • Hacking Ético y Pentesting (Red Team)
      • Análisis de Malware e Ingeniería Forense
      • Seguridad Defensiva y Cumplimiento (Blue Team)
      • Ciberseguridad Estratégica
    • Liderazgo y Habilidades Blandas
      • Fundamentos de Habilidades Profesionales
      • Liderazgo y Gestión de Equipos
      • Comunicación Avanzada y Oratoria
      • Negociación y Resolución de Conflictos
      • Inteligencia Emocional y Autogestión
      • Productividad y Herramientas Digitales
      • Gestión de Proyectos y Metodologías Ágiles
      • Desarrollo de Carrera y Marca Personal
      • Diversidad, Inclusión y Entorno Laboral Saludable
      • Filosofía y Estrategia para Líderes
    • Diseño de Producto y UX
      • Fundamentos de Diseño UX/UI
      • Investigación de Usuarios (UX Research)
      • Arquitectura de Información y Usabilidad
      • Diseño de Interfaces y Prototipado (UI Design)
      • Sistemas de Diseño y DesignOps
      • Redacción UX (UX Writing)
      • Creatividad e Innovación en Diseño
      • Diseño Accesible e Inclusivo
      • Diseño Asistido por Inteligencia Artificial
      • Gestión de Producto y Liderazgo en Diseño
      • Diseño de Interacciones Emergentes (VUI/VR)
      • Desarrollo Web para Diseñadores
      • Diseño y Prototipado No-Code
    • Contenido Audiovisual
      • Fundamentos de Producción Audiovisual
      • Producción de Video para Plataformas Digitales
      • Producción de Audio y Podcast
      • Fotografía y Diseño Gráfico para Contenido Digital
      • Motion Graphics y Animación
      • Contenido Interactivo y Realidad Aumentada
      • Estrategia, Marketing y Monetización de Contenidos
    • Desarrollo Móvil
      • Fundamentos de Desarrollo Móvil
      • Desarrollo Nativo Android con Kotlin
      • Desarrollo Nativo iOS con Swift
      • Desarrollo Multiplataforma con React Native
      • Desarrollo Multiplataforma con Flutter
      • Arquitectura y Patrones de Diseño Móvil
      • Integración de APIs y Persistencia Móvil
      • Testing y Despliegue en Móvil
      • Diseño UX/UI para Móviles
    • Diseño Gráfico y Arte Digital
      • Fundamentos del Diseño Gráfico y Digital
      • Diseño de Identidad Visual y Branding
      • Ilustración Digital y Arte Conceptual
      • Diseño Editorial y de Empaques
      • Motion Graphics y Animación 3D
      • Diseño Gráfico Asistido por Inteligencia Artificial
      • Creatividad e Innovación en Diseño
    • Programación
      • Fundamentos de Programación e Ingeniería de Software
      • Herramientas de IA para el trabajo
      • Matemáticas para Programación
      • Programación con Python
      • Programación con JavaScript
      • Programación con TypeScript
      • Programación Orientada a Objetos con Java
      • Desarrollo con C# y .NET
      • Programación con PHP
      • Programación con Go y Rust
      • Programación Móvil con Swift y Kotlin
      • Programación con C y C++
      • Administración Básica de Servidores Linux
    • Negocios
      • Fundamentos de Negocios y Emprendimiento
      • Estrategia y Crecimiento Empresarial
      • Finanzas Personales y Corporativas
      • Inversión en Mercados Financieros
      • Ventas, CRM y Experiencia del Cliente
      • Operaciones, Logística y E-commerce
      • Gestión de Proyectos y Metodologías Ágiles
      • Aspectos Legales y Cumplimiento
      • Habilidades Directivas y Crecimiento Profesional
      • Diversidad e Inclusión en el Entorno Laboral
      • Herramientas Digitales y Automatización para Negocios
    • Blockchain y Web3
      • Fundamentos de Blockchain y Web3
      • Desarrollo de Smart Contracts y dApps
      • Finanzas Descentralizadas (DeFi)
      • NFTs y Economía de Creadores
      • Seguridad Blockchain
      • Ecosistemas Blockchain Alternativos (No-EVM)
      • Producto, Marketing y Legal en Web3
    • Recursos Humanos
      • Fundamentos y Cultura Organizacional en RRHH
      • Atracción y Selección de Talento
      • Cultura y Employee Experience
      • Gestión y Desarrollo de Talento
      • Desarrollo y Evaluación de Liderazgo
      • Diversidad, Equidad e Inclusión
      • AI y Automatización en Recursos Humanos
      • Tecnología y Automatización en RRHH
    • Finanzas e Inversiones
      • Fundamentos de Finanzas Personales y Corporativas
      • Análisis y Valoración Financiera
      • Inversión y Mercados de Capitales
      • Finanzas Descentralizadas (DeFi) y Criptoactivos
      • Finanzas y Estrategia para Startups
      • Inteligencia Artificial Aplicada a Finanzas
      • Domina Excel
      • Financial Analyst
      • Conseguir trabajo en Finanzas e Inversiones
    • Startups
      • Fundamentos y Validación de Ideas
      • Estrategia de Negocio y Product-Market Fit
      • Desarrollo de Producto y Operaciones Lean
      • Finanzas, Legal y Fundraising
      • Marketing, Ventas y Growth para Startups
      • Cultura, Talento y Liderazgo
      • Finanzas y Operaciones en Ecommerce
      • Startups Web3 y Blockchain
      • Startups con Impacto Social
      • Expansión y Ecosistema Startup
    • Cloud Computing y DevOps
      • Fundamentos de Cloud y DevOps
      • Administración de Servidores Linux
      • Contenerización y Orquestación
      • Infraestructura como Código (IaC) y CI/CD
      • Amazon Web Services
      • Microsoft Azure
      • Serverless y Observabilidad
      • Certificaciones Cloud (Preparación)
      • Plataforma Cloud GCP

    Platzi y comunidad

    • Platzi Business
    • Live Classes
    • Lanzamientos
    • Executive Program
    • Trabaja con nosotros
    • Podcast

    Recursos

    • Manual de Marca

    Soporte

    • Preguntas Frecuentes
    • Contáctanos

    Legal

    • Términos y Condiciones
    • Privacidad
    • Tyc promociones
    Reconocimientos
    Reconocimientos
    Logo reconocimientoTop 40 Mejores EdTech del mundo · 2024
    Logo reconocimientoPrimera Startup Latina admitida en YC · 2014
    Logo reconocimientoPrimera Startup EdTech · 2018
    Logo reconocimientoCEO Ganador Medalla por la Educación T4 & HP · 2024
    Logo reconocimientoCEO Mejor Emprendedor del año · 2024
    De LATAM conpara el mundo
    YoutubeInstagramLinkedInTikTokFacebookX (Twitter)Threads