por primera vez en el curso logre entender el funcionamiento de los reducer y actions y logre codear el logout sin ver la clase
Bienvenida al curso
Todo lo que aprenderás sobre React Router y Redux
¿Qué es React Router? y Aplicarlo en tus proyectos
¿Qué es React Router y cómo instalarlo?
Crear nuestro archivo de Rutas
Container: Login
Container: Register
Container: 404 Not Found
Componente: Layout
Manejando enlaces y configuraciones
¿Qué es Redux?
Qué es Redux
¿Qué es Redux? Profundizando en la herramienta
Instalación de Redux
Creando el Store de Redux
Aplicando Redux a nuestra aplicación
Creando los reducers
Finalizando reducers y eliminar favoritos
Debuggeando nuestro proyecto (agregando validaciones a nuestro componente card)
Crear Formulario de Login
Formulario de Login con Redux
Creando un Servicio para Gravatar
Uso de gravatar en nuestro proyecto
Validación para LogIn LogOut
Register
Register con Redux
Vista general del player
Arreglando la funcionalidad del player
Terminando de detallar nuestro player
Validaciones
Validaciones de UI
Debug con Redux Devtools
Cierre del curso
Cierre del Proyecto
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 63
Preguntas 17
por primera vez en el curso logre entender el funcionamiento de los reducer y actions y logre codear el logout sin ver la clase
Al fin pude entender el sentido de Redux, definitivamente es necesario practicar e intentar hacer las cosas sin ayuda.
Básicamente, la función connect recibe dos parámetros
mapStateToProps y mapDispatchToProps
En palabras resumidas, la primera solicita datos del store(la base de datos)
y el segundo envía datos.
Así solamente hay un flujo de datos y todo es mas simple. Me exploto la cabeza. Animo para aquellos que aun están batallando
Reto:
import PropTypes from 'prop-types';
...
Header.propTypes = {
user: PropTypes.object
}
Hola creo que todo se peude poner dentro de una validacion de hasUser no necesitamos dos :
{hasUser ? (
<>
<li>
<a href='/'>{user.name}</a>
</li>
<li>
<a href='#logout' onClick={handleLogout}>Cerrar Sesión</a>
</li>
</>
) : (
<li>
<Link to='/login'>Iniciar Sesión</Link>
</li>
)}```
Epico! con redux y configurando los actions manejando todo desde un mismo estado es increíble cómo se ahorra código y todo sale como magia. Hermoso!
Nota: al principio pensé que mapDispatchToProps se tenía que llamar así por obligación, pero yo le puse mapActions e igual funciona.
const mapActions = {
logoutRequest
}
export default connect(mapStateToProps,mapActions)(Header)
Este era el ejemplo que buscaba sobre como conviven ambas partes, el mapStateToProps y el mapDispatchToProps
Reto:
Header.propTypes = {
user: PropTypes.object.isRequired,
logoutRequest: PropTypes.any.isRequired,
};
Muy bien explicado, de los mejores profes, demuestra experiencia y transmite seguridad.
Hacer un breve repaso al final de la clase es muy útil para atar cabos sueltos. Deberían realizarlo más seguido los otros profes cuando se abarcan varios conceptos que pueden ser confusos. 🙃
🦄 Acá el código de lo que llego hasta el momento: https://github.com/AndresCampuzano/React-Router-and-Redux/commit/94290b811ed0c0a04ed723f7e6adb48c3ff5dae8
Reto:
CarouselItem.jsx
CarouselItem.propTypes = {
id: PropTypes.number,
cover: PropTypes.string,
title: PropTypes.string,
year: PropTypes.number,
contentRaiting: PropTypes.string,
duration: PropTypes.number,
isList: PropTypes.bool,
setFavorite: PropTypes.func,
deleteFavorite: PropTypes.func,
};
Header.jsx
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func,
};
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import gravatar from '../utils/gravatar';
import { logoutRequest } from '../actions';
import '../assets/styles/components/Header.scss';
import logo from '../assets/static/logo-platzi-video-BW2.png';
import userIcon from '../assets/static/user-icon.png';
const Header = (props) => {
const { user } = props;
const hasUser = Object.keys(user).length > 0;
const handleLogout = () => {
props.logoutRequest({});
};
return (
<header className='header'>
<Link to='/'>
<img className='header__img' src={logo} alt='Platzi Video' />
</Link>
<div className='header__menu'>
<div className='header__menu--profile'>
{hasUser ?
<img src={gravatar(user.email)} alt={user.email} /> :
<img src={userIcon} alt='iconodeusuario' />}
<p>Perfil</p>
</div>
<ul>
{hasUser ?
<li><a href='/'>{user.name}</a></li> :
null}
{hasUser ?
<li><a href='#logout' onClick={handleLogout}>Cerrar Sesión</a></li> : (
<li>
<Link to='/Login'>
Iniciar sesión
</Link>
</li>
)}
</ul>
</div>
</header>
);
};
const mapStateToProps = (state) => {
return {
user: state.user,
};
};
const mapDispactchToProps = {
logoutRequest,
};
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func.isRequired,
};
export default connect(mapStateToProps, mapDispactchToProps)(Header);
import PropTypes from 'prop-types';
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func,
};
para que sirve la parte de object.keys(user) ?
El user.name no tiene ningun valor
Reto
import PropTypes from 'prop-types';
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func,
};
Reto
import PropTypes from 'prop-types';
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func.isRequired,
};```
No puedo creerlo … 3 clases con el mismo error, revisen bien su código.
En login.jsx
const handleSubmit = (event) => {
event.preventDefault(); //*Para que no se haga la acción de enviar formulario
props.loginRequest(form);
props.history.push('/'); //*Redirigimos al usuario al home
};
loginRequest NECESITA EL PARAMETRO DE FORM. Si no, no funciona el login.
Apuntes extras:
Básicamente, la función connect recibe dos parámetros:
En palabras resumidas, la primera solicita datos del store(la base de datos)
y el segundo envía datos y dispara acciones para interactuar con el store.
Así solamente hay un flujo de datos y todo es mas simple.
Documentación oficial de Verificación de tipos con PropTypes - React
Para para saludar al usuario se puede añadir el nombre: en Login.jsx:
const [form, setValues] = useState({
name: "",
email: "",
password: "",
});
…
<input
name="name"
className="input"
type="text"
placeholder="Nombre"
onChange={handleInput}
/>
…
y en Header.jsx:
{hasUser ? (
<>
<li>
<a href="/">{`Bienvenido ${user.name}`}</a>
</li>
<li>
<a href="#logout" onClick={handleLogout}>
Cerrar Sesión
</a>
</li>
</>
Reto superado
Por experiencia de usuario, creo que en lugar de mostrarle la seccion de perfil cuando aun no ha hecho login, podrian mostrarle directamente el enlace del login con un renderizado condicional. Asi, el usuario vera una imagen y un menu solo cuando este logeado…
Vamos a trabajar las validaciones con nuestro header que nos permitira saber si estamos logeados o no.
Crearemos la validacion en nuestro menu, donde teniamos cuenta o iniciar sesion. Y Utilizaremos a hasUser para poder confimarlo. Primero crearemos validaciones para la interfaz
<ul>
{hasUser ? <a href="/">{user.name}</a> : null}
{hasUser ? (
<li>
<a href="#logout" onClick={handleLogout}>
Cerrar Sesion
</a>
</li>
) : (
<li>
<Link to="/login">Iniciar Sesión</Link>
</li>
)}
</ul>
Asi nuestro menu se vera diferente en cao de que iniciemos o no sesion
Ahora crearemos un action nuevo para poder desloguearnos, esto en actions
export const logoutRequest = (payload) => ({
type: "LOGOUT_REQUEST",
payload,
});
Ahora lo importaremos en Header
import { logoutRequest } from "../actions";
Pero recordemos que tenemos que mapiar nuestra informacion
const mapDispatchToProps = {
logoutRequest,
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);
Ahora vamos en la funcion hacer lo siguiente:
const handleLogout = () => {
props.logoutRequest({});
};
Donde le mandaremos un objeto vacio y asi simular un logout.
Ahora solo crearemos nuestro reducer
case "LOGOUT_REQUEST":
return {
...state,
user: action.payload,
};
Otra forma de mapear los actions:
export default connect(mapStateToProps, { logoutRequest })(Header);
De esta forma te ahorras hacer la funcion mapDispatchToProps.
de verdad que escogí el peor curso para hacer un proyecto personalizado, este era el que tenia que seguir al pie de la letra
es interesante como en todo el proyecto no se generó una configuración de eslint o prittier
Hasta aquí parece ordenado, pero me preocupan los estilos CSS,
Depronto me perdi de algo pero cuando el profe le pone nombre a las funcion como mapDispatchToProps es por que debe ser asi o por que el quiere ponerle asi ? 🤔🤔
Podríamos modificar la etiqueta a por un Link ya que de esta forma cuando cerremos sesión no se recargue nuestra página 😄
Seria algo así lo del reto pero no entiendo por que se pasan esos proptypes.
import PropTypes from 'prop-types';
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func,
};
Es correcto poner como proptypes las props de redux? O solo se ponen las que puede recibir el componente si es instanciado por otro?
a
Practicas:
Qué tal, ¿cómo le puedo hacer para que persistan los datos del usuario previamente logrado cuando recargue la pagina o vuelva a abrir el navegador?
¿A alguíen más le aparece la contraseña cuando inician sesión?
profe excelente forma de explicar
Como seria para hacer esta misma validacion pero con hooks?
Reto:
import PropTypes from 'prop-types';
// ...
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func,
}
// ...
Una validación mas simple:
{ hasUser && <li><a href="/">Cuenta</a></li> }
Para la validacion seria desde el login antes de estar en header
Que buen curso 😄
No queda iniciada la sesión simulada. Siempre redirecciona al home pero me sigue apareciendo iniciar sesión, y gravatar tampoco lo toma.
mi github
https://github.com/ruben-xe
import Proptypes from 'prop-types';
Header.propTypes = {
user: Proptypes.object,
logoutRequest: Proptypes.func,
}
He llegado hasta aquí y no me queda claro como funciona lo de mandar un objeto vacío para reiniciar el estado (State)
Muy bueno!
Quise hacer que cuando cerrará sesión, le den en logoutRequest luego pueda ir a la ruta /login pero me da este error:
Este es el código que coloque:
const handleLogout = () => {
props.logoutRequest({});
props.history.push("/login");
}
¿Que podría estar mal?
Me está costando mucho más que antes seguir la lógica que se usa. Voy a tener que repasar bastante
Reto de autenticar los props con los propTypes
// validaciones con prop-types
Header.propTypes = {
// el user debe de ser un objeto
user: propTypes.object,
// el logoutRequest debe ser una funcion
logoutRequest: propTypes.func,
};
mi propuesta para el menu
<ul>
{hasUser ? (
<>
<li>
<Link to='/login'>{user.email}</Link>
</li>
<li>
<a href='#logout' onClick={handleLogout}>
Cerrar Sesión
</a>
</li>
</>
) : (
<li>
<Link to='/login'>Iniciar Sesión</Link>
</li>
)}
</ul>;
Hola! Buena clase!
…
…
.
hasUser=> Nos va a permiti saber si tenemos o no una cuenta iniciada.
…
…
…
…
…
…
Estuvo excelente la clase, Redux es como magia… Con apenas unas líneas de código cambiamos el estado de un componente, y no nos preocupamos por datos redundantes porque todo viene de un solo lugar, el store! GENIAL
Para los que vieron el detalle de user.name, cámbienlo a user.email. Y si se les desborda el contenido, pueden modificar la propiedad width del ul a max-content.
Alguien me podría decir una definición de Payload?
El reto quedaría así :
import PropTypes from "prop-types";
..........
Header.propTypes = {
user: PropTypes.object.isRequired,
logoutRequest: PropTypes.func,
}
Header.propTypes = {
user: PropTypes.object.isRequired,
logoutRequest: PropTypes.func.isRequired
}```
`import PropTypes from ‘prop-types’;
Header.propTypes = {
user: PropTypes.object,
logoutRequest: PropTypes.func,
};`
{
hasUser ?
<>
<li><a href="/">{user.name}</a></li>
<li>
<a href="#" onClick={handlerLogout}>Cerrar Sesión</a>
</li>
</>:
<li>
<Link to="/login">Iniciar sesión</Link>
</li>
}
Hola gente, tengo un Warnig al agregar los propTypes, me corre bien el sitio, pero en consola me muestra este mensaje
En este ejemplo de login y logout, tanto las acciones como los reducers están comportandose de la misma manera y esto, en proyectos grandes se convierte en redundancia de código. El siguiene patrón puede ser usado:
accion/index.js
export const manageLogin = payload => ({
type: "MANAGE_LOGIN",
payload,
});
accion/index.js
case "MANAGE_LOGIN":
return {
...state,
user: action.payload,
};
No entiendo la funcionalidad de PropTypes, para que se usan? son relevantes? existe alguna clase donde lo expliquen?
Porque en la validacion hasuser usa la etiqueta <a> en vez de <Link>?
Muy bien!
Dejo mio reto y la documentaciòn de propTypes que està buenisima para entender, ya que en principio habìa puesto a user : PropTypes.string, cuando realmente es PropTypes.object.
Ademas la misma documentaciòn brinda un montòn de hacks para que puedas hace aùn màs puntual tus especificaciones.
Header.propTypes = {
user : PropTypes.object.isRequired,
logoutRequest : PropTypes.func.
}
https://es.reactjs.org/docs/typechecking-with-proptypes.html
Como puedo inyectar el history en las props del header?, en los demás componentes si me funciona pero en el header no, no sé si este relacionado con que no esta directamente agregado en las rutas.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?