No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de React Router 5 y Redux

Curso de React Router 5 y Redux

Oscar Barajas Tavares

Oscar Barajas Tavares

Validaciones

26/29
Recursos

Aportes 25

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Logre hacer esta validacion sin necesidad de agregar un paquete extra, para ello utilice el hook useLocation desde react router dom, les comparto mi codigo

import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import { connect } from 'react-redux';

import { logoutRequest } from '../actions/'
import gravatar from '../utils/gravatar';
import '../assets/styles/components/Header.scss';
import logo from '../assets/images/logo-platzi.png';
import userIcon from '../assets/images/profile-user.svg';

const Header = (props) => {

   const { user } = props
   const userLogedIn = () => user.email !== undefined; /* Verificamos si nuestro usuario ya tiene un email registrado en su sesion */
   const handleLogout = () => {
      props.logoutRequest({}) /* Le pasamos un objeto vacio como payload que sera lo que se establezca en el reducer */
   }

   const headerClass = (useLocation().pathname === '/register' || useLocation().pathname === '/login') ? 'greenHeader' : '';

   return(
      <header className={`header ${headerClass}`}>
         {console.log(headerClass)}
         <Link to="/"> 
            <img className="header__img" src={ logo } alt="" />
         </Link> {/* Usamos el elemento link de react router dom, ya que nos permite poder
         desplazarnos por nuestra aplicacion sin necesidad de hacer un refresh a la pagina completa */}
         <div className="header__menu">
            <div className="header__menu--profile">
               {userLogedIn() ?
                  <img src={ gravatar(user.email) } alt="user icon" />
                  :
                  <img src={ userIcon } alt="user icon" />
               }
               <p>Perfil</p>
            </div>
            {userLogedIn() ?
               <ul>
                  <li><p>Bienvenido <b>{user.name}</b></p></li>
                  <li><p>Mi perfil</p></li>
                  <li><a onClick={handleLogout}>Cerrar sesion</a></li>
               </ul>
               :
               <ul>
                  <li><Link to="/login">Iniciar sesion</Link></li>
                  <li><Link to="/register">Registrate</Link></li>
               </ul>
            }
         </div>
      </header>
   )};

const mapStateToProps = state => {
   return {
      user: state.user,
   }
}

const mapDispatchToProps = {
   logoutRequest
}
export default connect(mapStateToProps,mapDispatchToProps)(Header);

Con esto agrego una clase mas al header para así poder cambiarle simplemente el color con una propiedad css solo agregando y quitando la clase

ahora en mi css solo tuve que agregar esta clase

.greenHeader {
   background-color: #21C08B;
}```

Luego de ver la clase, quede triste, ya que me gustaba la ideal del Layout y la forma tan simple de ahorrar muchas repeticiones de llamadas a componentes y en general de código.

Pero al mismo tiempo pienso que debe haber una forma dinámica de establecer este tipo de cambios, sin tener que llamar el componentes desde cada container y componente que lo requiere.

Por esto se me ocurrió que podía establecer una propiedad en el state que almacena las clases de Header y crear un action que actualizara las clases dependiendo del container que se cargaba.

En ese caso cada container llama el action que actualiza la propiedad del state que almacena las clases del header.

y el header consulta esta propiedad y establece las clases del header.

pero este me generaba un Warning, finalmente lo solucione con un effect, que ejecuta el cambio de clase cuando ya todo se ha renderizado, y funciona.

Si alguien también lo esta intentando, o sabe como lograrlo de una forma mucho mejor me encantaría aprender.

propiedad nueva en el state:

const initialState = {
    "user":{},
    "playing": {},
    "headerClass": ['header'], 
     ... lo demas..
}

Luego en el index.js de actions, se genera una nueva action para actualizar esta propiedad

export const changeClassHeader = payload => ({
  type: actions.changeClassHeader,
  payload,
})

En el el index.js de los reduces, se crea un nuevo case, que reciba y realice la actualziación del state, con el cambio en la propiedad del state que almacena las clases.

    case actions.changeClassHeader:

      state.headerClass = action.payload
      console.log(state)
      return {
        ...state        
      }
      

Por último en cada container, se añade el action y se ejecuta el un useEffect para que no genere errores la aplicación y se renderice el cambio de forma correcta luego de haber renderizado el container inicial.

Ejemplo del código en el container Login

  useEffect(() => {
    props.changeClassHeader(['isLogin']);
  })

Muchas gracias a todos por sus aportes en otras clases, eso me ha ayudado mucho, quedo atento a sus provechos comentarios para seguir aprendiendo.

Bueno yo si desde un principio le puse un color oscuro al fondo entonces no tuve que hacer esto

Login

…
Registro

…
Maquetacion

…
Parte del Video

…
😃

Yo simplemente modifique los estilos de los componentes con un gradiente de 3 colores y me parecia un resultado mejor para poder mantener el header en el layot.

background-image: linear-gradient(#8f57fd, #21c08b, #8f57fd);

En esta clase vemos como generar clases dinámicas con la dependencia classname.

# npm
npm install classnames
# Bower
bower install classnames
# Yarn
yarn add classnames

Esta utilidad nos permite añadir clases según se cumplan x condiciones.
Ejemplos:

import classNames from 'classnames';

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'

Aqui les dejo la documentacion del paquete classnames para que le echen un ojo… o dos si quieren 👀 -> (https://www.npmjs.com/package/classnames)

En mi caso preferí usar un action/reducer para realizar este cambio 😃

Actions:

export const setHeader = (payLoad) => ({
  type: actions.setHeader,
  payLoad,
});

reducers:

case actions.setHeader:
      return {
        ...state,
        isForm: action.payLoad,
      };

Login

useLayoutEffect(() => {
    props.setHeader(true);
  }, []);

Por si quieren saber más sobre el className aquí está este link

Esto se pudo resolver facilmente con operador || y template strings, en vez de usar una dependencia extra

Prácticas:

🤯🤯🤯 Genial !!

Yo lo hice de esta forma, sin instalar classnames, espero les sirva

const headerClass = () => { 
	if (isLogin) return 'isLogin'
	if (isRegister) return 'isRegister'
}

return (
	<header className={`header ${headerClass()}`}>
	// ...

de hecho lo hice desde un inicio

envio el distintivo como props

lo recivo y lo concateno en el className

esta es el archivo del estilo donde esta declarada la clase

Genial! Se puede ver claramente en los aportes de cada uno que no existe una única manera de resolver un problema…
Existen muchas formas de resolver el problema de esta clase. Leer cada aporte me abre a la mente a ver otras soluciones que puedo aplicar en otros tipos de problemas y no solamente en este.

Encontre una forma más sencilla si usar ese paquete y que el header quede en el Layout.jsx, en la carpeta utils cree un archivo llamado classname.js que validara la ruta actual y dependiendo a esa ruta se agregue la clase,

classname.js

/**
 *
 * className
 * @param {String} name
 * clase dependiendo de la ruta
 * @param {{currentRoute: String, classnames: {fo: '/bar'}}} options
 */

export default function className(name, options) {
    let newClassName = name
    console.log(name)
    for (const option in options.classnames) {
        if (options.classnames[option] === options.currentRoute) {
            newClassName = `${newClassName} ${option}`
        }
    }

    return newClassName
}

Luego la utilize en el Header.jsx así:

    const backgroundHeader = className('header', {
        currentRoute: useLocation().pathname,
        classnames: {
            isLogin: '/login',
            isRegister: '/register',
        },
    })

Funciona comparando cada ruta de classnames con currentRoute y si coincide alguna por ejemplo /login entonces agrega la clase isLogin.

Luego solo es pasar la variable backgroundHeader al className de la etiqueta header, useLocation lo pueden importar de react-router-dom: import { useLocation } from 'react-router-dom'. La idea de usar ese hook es de un aporte anterior

Para crear el player utilizaremos todo lo que ahora sabemos y algunas cosas nuevas

  • Tenemos la redireccion por medio del boton reprocir de los componentes, nos redireccionará a la ruta player/01 por ejemplo

    <Link to={`player/${id}`}>
        <img className='carousel-item__details--img' src={iconPlay} alt='Play Icon' />
    </Link>
    

esto se puede hacer con templates literal y useState sin usar paquetes extra

Casi que no me funciona, yo tenía unos ligeros estilos diferentes y se veía raro, pero lo logre solucionar 😄

Van agregando esta clase

Se olvidó de agregarle <Header> también al componente <NotFound>

const NotFound = (props) => {

    useEffect(() => {
        document.title = "NotFound";
    }, []);

    return (
        <Fragment>
            <Header/>

            <section className="error">
                <div className="error_main">
                    <h1 className="animated pulse">Error 404/h1>
                    <label>Página no encontrada</label>
                </div>
            </section>
        </Fragment>
    )
}

Como toda la magia ocurria en el home para cambiar la imagen borre el layout e importe el header en cada pagina y en el home le agregue el prop userIsTrue y agregue esta condicion en el header y cambie el nombre de la clase y elimine la imagen del usuario ya que esta no estaba en el diseño

{userIsTrue ? (
				<header className="header__home">
					<Link to="/">
						<img className="header__img" src={logo} alt="Platzi Video" />
					</Link>
					<div className="header__menu">
						<div className="header__menu--profile">
							<img
								src={hasUser > 0 ? gravatar(user.email) : userIcon}
								alt={user.email}
							/>
							<p>Perfil</p>
						</div>
						<ul>
							{hasUser ? (
								<li>
									<Link to="/">{user.name}</Link>
								</li>
							) : null}

							{hasUser ? (
								<li>
									<Link to="#logout" onClick={handleLogout}>
										Cerrar sesión
									</Link>
								</li>
							) : (
								<li>
									<Link to="/login">Iniciar sesión</Link>
								</li>
							)}
						</ul>
					</div>
				</header>
			) : (
				// Codigo si el userIsTrue es False
				<header className="header">
					<Link to="/">
						<img className="header__img" src={logo} alt="Platzi Video" />
					</Link>
				</header>
			)}

Excelente Clase, me gustó mucho!

n

casi casi. me sale igual… =(