Decidí hacer el display del menú de está forma, se me hace más bonito :3
{toggle ? <Menu /> : ""}
Introducción
¿Qué es React.js?
Conceptos fundamentales de React
Configurando el entorno de desarrollo
Instalación de React y React DOM
Configuración de Webpack y Babel
Cambios en tiempo real con Webpack
React con CSS y Sass
Maquetación en React
Transformando HTML y CSS en componentes de React
Estilos en los componentes de React
Páginas, rutas y componentes
React Router DOM
Navegación entre rutas
Header en todas las rutas
¿Qué es Atomic Design?
Solución al reto: componentes y rutas de React Shop
Tipos de componentes en React: stateful vs. stateless
Imágenes y alias en Webpack
React Hooks
React.useState
Toggle del menú
useEffect y consumo de APIs
Custom Hooks para la tienda
useRef y formularios
React Context
Completando el carrito de compras
Orden de compra
Calculando el precio total
Eliminando productos del carrito
Deploy
Cómo comprar tu dominio y conexión con Cloudflare
Automatizando el despliegue con GitHub Actions
Próximos pasos
Retos de React.js (bug hunters)
Continúa con el Curso Práctico de Next.js
Aún no tienes acceso a esta clase
Crea una cuenta y continúa viendo este curso
Aportes 22
Preguntas 5
Decidí hacer el display del menú de está forma, se me hace más bonito :3
{toggle ? <Menu /> : ""}
Primero, importemos el componente menu
import Menu from '@components/Menu'
Segundo, incorporemos la lógica para el menu, tal que al momento de dar click en el correo del header, se muestre dicho menu. Para ello usaremos estado.
const Header = () => {
const [toggle, setToggle] = useState(false);
const handleToggle = () => {
setToggle(!toggle);
}
}
Inicializamos la variable toggle en falso, para que al inicio de la app, no se muestre. Luego creamos la función handleToggle que será invocado en algun evento. Esta tiene por dentro setToggle(!toggle). Lo que queremos decir, es que cada vez ocurra el evento, el estado de toggle será el opuesto booleano. En el html, se vería de la siguiente manera.
<div className="navbar-right">
<ul>
<li className="navbar-email" onClick={handleToggle}>
[email protected]
</li>
<li className="navbar-shopping-cart">
<img src={shoppingCart} alt="shopping cart" />
<div>2</div>
</li>
</ul>
</div>
{toggle && <Menu />}
En la etiqueta li con el className navbar-email, está el evento onClick, el cuál invoca la función del componente llamada handleToggle. Es decir, cada vez que demos click en el correo, la función cambiará el valor de toggle del estado, en pocas palabras. Para mostrar dicho Menu, más abajo tenemos una expresión la cual renderiza Menu solamente si toggle es verdadero.
Editemos un poco el scss para corregir unos errores al momento en que se muestra
.Menu {
width: 100px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute; //nuevo
top: 60px;
right: 50px;
}
Esta es mi solución para la clase .Menu
.Menu {
width: 100px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
top: 4rem;
right: 2rem;
}
React.useState:
import React, {useState} from ‘react’;
Crear const [uno, setUno] = useState(‘1’)
En el valor inicial o ‘1’ puede ir: bool, numero, string, objeto o array.
Manejando el evento del elemento que modificara su estado, activaremos la función que recibirá el evento y activara la función ‘setUno( )’ para modificar su valor, ej: setUno(‘2’)
Siempre que se recargue la página, el valor volverá a su valor inicial!
En la clase Oscar uso el operador &&
para hacer una validación, what, el mundo se volvió loc0, que esta pasando…?
.
Esto funciona porque el operador &&
lo que hace es una validación del primer argumento para decidir si pasar al siguiente. Por ejemplo, si nosotros hacemos esta validación en JS
if(0 < 1 && 1 < 0){
@something
}
Lo primero que hace JS es validar que 0 sea menor que 1, lo cual es correcto, entonces podemos pasar a la siguiente validación.
.
Ahora, si nosotros lo hacemos a la inversa
if(1 < 0 && 0 < 1){
@something
}
JS nota que la primera validación (1 < 0) es falsa, por lo que ya ni siquiera se molesta en ver si la siguiente es verdadera o no.
.
Ese es el principio sobre el cual nosotros podemos hacer validaciones de una sola variable con &&
En mi experiencia, yo puedo decirles que no nosotros como devs no vamos a querer modificar el estado directamente. Por ejemplo, en la clase el maestro hizo lo siguiente:
setToggle(!toggle)
Sin embargo, esta no es la mejor opción. Lo que queremos hacer es usar el estado que ya teníamos y modificarlo, la buena noticia es que nosotros podemos acceder a este estado desde la funcion setToggle
. Entonces, lo que podriamos hacer es lo siguiente:
setToggle(prevToggle => !prevToggle)
Asi, accedemos al estado que previamente teniamos y l o retornamos modificado, sin manipular el estado directamente.
.
OJO, esto solo es recomendable cuando queremos acceder al estado anterior. Si queremos modificar la variable toggle por un string por ejemplo, en ese caso, es muy valido hacer algo asi:
setToggle("Un string")
Mi solucion
.Menu {
width: 100px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
margin-top: 80px;
right: 25px;
}
Modifiqué un poquito el elemento donde desplegamos el toggle para que sea claro que es un elemento al cual podemos hacerle click:
.navbar-email:hover {
cursor: pointer;
color: var(--hospital-green);
}
Y yo haciendo menús con z-index, opacity y pointer-events… definitivamente el atomig design se ve bastante interesante; así no tendré que hacer cambios en los header de cada html sino en un solo archivo jsx optimizando el trabajo
De esta manera toma la posicion del padre por si llegamos a cambiar el tamaño del header siempre se vea justo debajo de este
nav {
display: flex;
justify-content: space-between;
padding: 0 24px;
border-bottom: 1px solid var(--very-light-pink);
position: relative;
}
.Menu {
width: 100px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
top: 100%;
right: 24px;
}
/Mi solucion al estilo del Menu/
.Menu {
width: 100px;
height: auto;
border: 1px solid var(–very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
top: 60px;
right: 55px;
}
//Aparte le hice un :hover al correo
.navbar-email {
color: var(–very-light-pink);
font-size: var(–sm);
margin-right: 12px;
border: .5px solid var(–very-light-pink);
border-radius: 3px;
padding: 1.5px;
transition: all 200ms ease-in-out;
}
.navbar-email:hover {
color: var(–hospital-green);
border: 1px solid var(–hospital-green);
}
Así solucione la posición del toggle menu
En diseño en figma requiere que se represente debajo del correo, para lo cual al elemento del header con clase .navbar-email le asigne position: relative
Al elemento con clase del Menu con clase .Menu le di position: absolute y use top/right
/* Style Header */
.navbar-email {
...
position: relative;
}
/*style Menu */
.Menu {
...
position: absolute;
rigth: 8%;
top: calc(24px + 37px); /* 24px padding-bottom nav | 37px (18px height .navbar-email - 1px border nav */
}
Solución al reto:
Agregue algo de CSS al componente Menu, se renderiza justo debajo del correo electrónico sin modificar las propiedades del navbar
<.Menu {
width: 100px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
margin-top: 60px;
margin-left: 1060px;
}>
Que locura de clase 🤭
Para que nos cambie el puntero en el email y sea más intuitivo el click podemos agregar
cursor: pointer;
Un intento de solucion:
.Menu {
position: absolute;
background-color: white;
width: 150px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
right: 50px;
top: 40px;
}
.Menu ul {
list-style: none;
padding: 10px;
margin: 0;
}
Mi solución
.Menu {
width: 100px;
height: auto;
border: 1px solid var(--very-light-pink);
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
right: 20px;
top: 60px;
}
mi solucion para que el menu se vea como debe ser usando styled component
import React from 'react'
import styled from 'styled-components'
import { Link } from 'react-router-dom'
const DesktopMenu = () => {
return (
<DesktopMenuStyled>
<List>
<Item>
<Link to={'/my-orders'}>My orders</Link>
</Item>
<Item>
<Link to={'/my-account'}>My account</Link>
</Item>
<Item>
<Link to={'/login'}>Sign out</Link>
</Item>
</List>
</DesktopMenuStyled>
)
}
export default DesktopMenu
const DesktopMenuStyled = styled.div`
width: 100px;
height: auto;
border: 1px solid #C7C7C7;
border-radius: 6px;
padding: 20px 20px 0 20px;
position: absolute;
top: 60px;
right: 0;
background-color: #FFFFFF;
`
const List = styled.ul`
list-style: none;
padding: 0;
margin: 0;
`
const Item = styled.li`
text-align: end;
&:nth-child(1),&:nth-child(2) {
font-weight: bold;
}
&:last-child a {
color: #2C68C2;
font-size: 14px;
}
& a {
text-decoration: none;
color: #000000;
margin-bottom: 12px;
display: inline-block;
}
`
PD: Les debo la imagen 🥲🥲 no se como subirla aqui
en mi caso como es una funcionalidad sencilla coloque una arrow function en mi componente que muestra el campo del email
const NavbarRight = () => {
const [isVisible, setIsVisible] = useState(false)
return (
<>
<Navbar>
<ul>
<NavbarEmail onClick={() => setIsVisible(!isVisible)}>
[email protected]
</NavbarEmail>
<NavbarShoppCart>
<img src={IconSHopCart} alt="shopping-cart" />
<div>2</div>
</NavbarShoppCart>
</ul>
</Navbar>
{ isVisible && <DesktopMenu /> }
</>
)
}
min 6:54, el bebeloper hace su aporte jeje
Les comparto mi solución, también les dejo el código que añadí al SCSS.
.desktop-menu {
position: absolute;
right: 60px;
top: 50px;
background-color: white;
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.