Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Práctico de React.js

Curso Práctico de React.js

Oscar Barajas Tavares

Oscar Barajas Tavares

Toggle del menú

17/29
Recursos

Aportes 22

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

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:

  1. import React, {useState} from ‘react’;

  2. Crear const [uno, setUno] = useState(‘1’)

    1. Donde ‘uno’ es la variable que modificara su estado, ‘setUno’ es la función que modificara su estado al suceder X cosa, y ‘1’ es el valor inicial que tendrá esa variable
  3. En el valor inicial o ‘1’ puede ir: bool, numero, string, objeto o array.

  4. 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’)

  5. Siempre que se recargue la página, el valor volverá a su valor inicial!

Porque podemos usar && como if statements?

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;
}