Cada día tengo mayor fluidez con React 😍
¡Bienvenida! Este es un curso especial de React Hooks
¿Qué aprenderás en el Curso Profesional de React Hooks?
¿Qué son los React Hooks y cómo cambian el desarrollo con React?
Introducción a React Hooks
useState: estado en componentes creados como funciones
useEffect: olvida el ciclo de vida, ahora piensa en efectos
useContext: la fusión de React Hooks y React Context
useReducer: como useState, pero más escalable
¿Qué es memoization? Programación funcional en JavaScript
useMemo: evita cálculos innecesarios en componentes
useRef: manejo profesional de inputs y formularios
useCallback: evita cálculos innecesarios en funciones
Optimización de componentes en React con React.memo
Custom hooks: abstracción en la lógica de tus componentes
Third Party Custom Hooks de Redux y React Router
Configura un entorno de desarrollo profesional
Proyecto: análisis y retos de Platzi Conf Store
Git Hooks con Husky
Instalación de Webpack y Babel: presets, plugins y loaders
Configuración de Webpack 5 y webpack-dev-server
Configuración de Webpack 5 con loaders y estilos
Loaders de Webpack para Preprocesadores CSS
Flujo de desarrollo seguro y consistente con ESLint y Prettier
Estructura y creación de componentes para Platzi Conf Store
Arquitectura de vistas y componentes con React Router DOM
Maquetación y estilos del home
Maquetación y estilos de la lista de productos
Maquetación y estilos del formulario de checkout
Maquetación y estilos de la información del usuario
Maquetación y estilos del flujo de pago
Integración de íconos y conexión con React Router
Integración de React Hooks en Platzi Conf Merch
Creando nuestro primer custom hook
Implementando useContext en Platzi Conf Merch
useContext en la página de checkout
useRef en la página de checkout
Integrando third party custom hooks en Platzi Conf Merch
Configura mapas y pagos con PayPal y Google Maps
Paso a paso para conectar tu aplicación con la API de PayPal
Integración de pagos con la API de PayPal
Completando la integración de pagos con la API de PayPal
Paso a paso para conectar tu aplicación con la API de Google Maps
Integración de Google Maps en el mapa de checkout
Creando un Custom Hook para Google Maps
Estrategias de deployment profesional
Continuous integration y continuous delivery con GitHub Actions
Compra del dominio y despliega con Cloudflare
Optimización de aplicaciones web con React
Integración de React Helmet para mejorar el SEO con meta etiquetas
Análisis de performance con Google Lighthouse
Convierte tu aplicación de React en PWA
Bonus: trabaja con Strapi CMS para crear tu propia API
Crea una API con Strapi CMS y consúmela con React.js
¿Qué sigue en tu carrera profesional?
Próximos pasos para especializarte en frontend
Crea una cuenta o inicia sesión
¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera
Oscar Barajas Tavares
Aportes 152
Preguntas 14
Cada día tengo mayor fluidez con React 😍
¡Hola!
Aquí comparto mi solución al reto:
Escribí un artículo en mi blog que quizás les ayude a complementar los conocimientos que Oscar transmitió en esta clase ❤❤
.
Link del articulo: https://dartiles.dev/blog/useeffect-react-hooks-ciclos-de-vida
.
.
Este blog es un claro reflejo de los conocimientos que adquirí en el curso practico de sapper y svelte de Oscar
Comparto el useEffect usando asyn/await
import React, { useState, useEffect } from "react";
const Characters = () => {
const [characters, setCharacters] = useState([]);
const getCharacters = async () => {
const response = await fetch("https://rickandmortyapi.com/api/character");
const data = await response.json();
setCharacters(data.results);
};
useEffect(() => {
getCharacters();
}, []);
return (
<div className="Characters">
{characters.map((character) => (
<h2 key={character.id}>{character.name}</h2>
))}
</div>
);
};
export default Characters;
useEffect nos permite manejar efectos que van a ser transmitidos dentro del componente.
En este ejemplo se llama a una API, traemos la información y la ejecutaremos en el componente
⠀
Characters.jsx
// importar useState y useEffect
import React, {useState, useEffect} from 'react'
const Characters = () => {
/**
* Lógica de useState
* constante donde internamente estructuramos los elementos que necesitamos
* de useState y lo iniciamos como un vector vacío
*/
const [characters, setCharacters] = useState([]);
/**
* Lógica de useEffect
* es una función con 2 parámetros
* el primero es una función anónima donde va a estar la lógica
* el segundo es una variable que esta escuchando si hay cambios
*/
useEffect(() => {
// useEffect llama a fetch, el cual obtiene la informacion de la api de RickAndMorty
fetch('https://rickandmortyapi.com/api/character/')
.then(response => response.json())
.then(data => setCharacters(data.results));
}, [])
/**
* Nombre del personaje
* Iteramos por cada uno de los elementos
*/
return (
<div className="Characters">
{characters.map(character => (
<h2>{character.name}</h2>
))}
</div>
)
}
export default Characters
⠀
App.js
import React from 'react'
// Importamos componente Header
import Header from './components/Header';
// Importamos componente Characters
import Characters from './components/Characters';
import './App.css';
function App() {
return (
<div className="App">
<Header />
<Characters />
<h1>
Hola Mundo
</h1>
</div>
);
}
export default App;
Como el darkmode es una variable global, subí la logica al nivel de App.js y desde header solo retorno la función que hace el cambio de color.
Usando bootstrap con sus clases para definir colores de texto y fondo, rapidamente puedes hacer este efecto de darkmode y responsive.
import "./App.css";
import React, { useState } from "react";
import { Header } from "./components/Header";
import Characters from "./components/Characters";
function App() {
const [darkMode, setDarkMode] = useState(false);
let bg = darkMode ? "bg-dark text-light" : "bg-light text-dark"
return (
<>
<div className= {"App "+ bg}>
<Header
darkMode={darkMode}
onClick={() => setDarkMode(!darkMode)}
></Header>
<Characters></Characters>
</div>
</>
);
}
export default App;
import React from 'react'
export const Header =( props )=>{
return(
<div className="Header ">
<h1>React Hooks</h1>
<button type="button" onClick={()=>props.onClick()}>
{props.darkMode ? "Light Mode" : "Dark Mode"}
</button>
</div>
)
}
import React, { useEffect, useState } from "react";
const Characters = () => {
const [characters, setCharacters] = useState([]);
useEffect(() => {
fetch("https://rickandmortyapi.com/api/character/")
.then((r) => r.json())
.then((data) => setCharacters(data.results));
}, []);
return (
<div className="container">
<div className="row">
{characters.map((character) => (
<div className="col">
<>
<img className="character__img" src={character.image} alt="" />
<h2 className="character__name">{character.name}</h2>
</>
</div>
))}
</div>
</div>
);
};
export default Characters;
Usando tailwindcss
import React, { useState, useEffect } from 'react';
const Characters = () => {
const [characters, setCharacters] = useState([]);
const API = 'https://rickandmortyapi.com/api/character/';
useEffect(() => {
fetch(API)
.then(response => response.json())
.then(data => setCharacters(data.results));
}, []);
return (
<section className="text-gray-700 body-font ">
<div className="flex flex-col text-center w-full mb-20">
<h1 className="sm:text-3xl text-2xl font-medium title-font mb-4 text-gray-900">Rick and Morty</h1>
<p className="lg:w-2/3 mx-auto leading-relaxed text-base">All Characters</p>
</div>
<div className="container px-5 mx-auto ">
<div className=" flex flex-wrap -m-2">
{characters.length > 0 && characters.map(character => (
<div className="p-2 lg:w-1/3 md:w-1/2 w-full">
<div className="h-full flex items-center border-gray-200 border p-4 rounded-lg">
<img alt="team" className="w-16 h-16 bg-gray-100 object-cover object-center flex-shrink-0 rounded-full mr-4" src={character.image} />
<div className="flex-grow">
<h2 className="text-gray-900 title-font font-medium">{character.name}</h2>
<p className="text-gray-500">{character.status}</p>
<p className="text-gray-500">{character.species}</p>
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
};
export default Characters;
useEffect
Nos ayuda con todo lo que tiene que ver con efectos secundarios. Algunos ejemplos de efectos secundarios son:
-Peticiones de datos
-Establecimiento de suscriptores
-Actualizaciones manuales del DOM
**Características de useEffect **
-Recibe dos parámetros: el primero una función y el segundo un array cuyos valoren serán variables de las que depende nuestro efecto(este array es opcional).
-Se va a ejecutar en cada renderizado del componente incluyendo el primero.
-Puedes usar más de un useEffect x componente
-Está diseñado para que la función que pases como parámetro retorna a su vez otra función, React va a ejecutar dicha función cuando se desmonte el componente
(BONUS) Como funciona el ciclo de vida de un componente?
OJO el ciclo de vida de un componente es un concepto para trabajar con componente de tipo clases, pero se me hacía interesante entender como funcionaba.
Veremos solo como funciona por encima cada ciclo tiene sus propios componentes para poder manejarlo.
El ciclo de vida de React se puede dividir en 3 fases, que son: Él montando, la actualización y el desmontado
Montado: Esta es la primera fase y ocurre una vez por componente cuando este se crea y se monta en la UI.
Actualización: Esta puede ocurrir ninguna o múltiples veces, esta fase sucede cuando ocurre algún cambio en el componente y por lo tanto requiere que la UI se vuelva a generar para que se puedan percibir estos cambios.
Desmontado: Es la última fase y se puede ejecutar un método antes de que se desmonte el componente de la UI.
¿Cuál es la diferencia entre el useEffect y los metodos del ciclo de vida?
La diferencia esta en que cuando usamos useEffect no pensamos en el cuando(en que fase estamos) si no, en el por qué el efecto se va a ejecutar(cambios en una dependencia).
Para profundizar les comparto lo siguiente blog: https://matiashernandez.dev/react-useeffect-hook-comparado-con-los-estados-del-ciclo-de-vida
Challenge done
Asi va quedando el mio:
Y así quedo. 😃
Esta es mi solución al reto, utilice una API que encontré de Breaking Bad para retarme y ver que realmente comprendi todo! (antes de este curso hice el de consumo de API muy recomendado)
En este articulo Dan Abramov explica el useEffect a profundidad
https://overreacted.io/a-complete-guide-to-useeffect/
Para realizar el cambio de estilo hice un levantamiento de estado, es decir pase el estado de darkMode en Header.jsx hacia App.js. Me quedo algo asi:
Header.jsx
import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';
const Header = (props) => {
// const [darkMode, setDarkMode] = useState(false);
// const appClass = document.getElementById('header');
// console.log(appClass);
return (
<div id="header" className="Header">
<h1>ReackHooks</h1>
<button
className="btn btn-dark"
onClick={props.onHandleClick}
type="button"
>
{
props.darkMode?
'DarkMode':
'LightMode'
}
</button>
</div>
)}
export default Header;
En app.js
import React, { useState } from "react";
import Character from "./components/Character";
import Header from "./components/Header";
import "./App.css";
function App() {
const [darkMode, setDarkMode] = useState(false);
const handleClick = () => {
setDarkMode(!darkMode);
const candleButton = document.querySelector(".App");
const title = document.querySelector(".App__title");
candleButton.classList.toggle("dark-background");
title.classList.toggle("dark-title");
};
return (
<div className="App">
<h1 className="App__title">Rick and Morty Characters</h1>
<Header onHandleClick={handleClick} darkMode={darkMode} />
<Character />
</div>
);
}
export default App;
En el navegador…
.
LightMode
.
.
DarkMode
Me faltó el dark/light mode, pero mañana continuo xD
Comparto mi versión del ejercicio
Apuntes
conceptos claves
useEffect.- El Hook de efecto te permite llevar a cabo efectos secundarios en componentes funcionales:
useEffect
hace disponibles los métodos del ciclo de vida componentDidMount
, componentDidUpdate
y componentWillUnmount
combinados en componentes funcionales. Tener presente que si no se pasa un array como segundo argumento:
useEffect(() => {
// aquí va el código
});
el código dentro de useEffect
se ejecutará cada vez que el componente se re-renderiza (la primera vez que es renderizado y en cada actualización). Similar a componentDidMount
y componentDidUpdate
.
Pasando un array vacío como segundo argumento:
useEffect(() => {
// aquí va el código
}, []);
el código se ejecuta una vez cuando el componente es montado (componentDidMount
).
Pasando un array no vacío como segundo argumento:
useEffect(() => {
// aquí va el código
}, [value])
el código se ejecutará cada vez que el valor (value) cambia. También puedes pasar mútiples valores y React renderiza el componente si cualquiera de los elementos del arreglo cambió.
useEffect
puede retornar una función el cual se ejecuta cuando el componente se desmonta (componentWillUnmount
).
useEffect(() => {
// código
return () => {
// código
}
});
Me hice un componente simple usando sass :B
import React, { useState, useEffect } from 'react';
import '../styles/Characters.sass';
const Characters = () => {
const [Characters, setCharacters] = useState([]);
useEffect(() => {
fetch('https://rickandmortyapi.com/api/character/')
.then(res => res.json())
.then(data => setCharacters(data.results));
}, []);
return (
<div class="container">
{Characters.map(character => (
<div className="card">
<figure>
<img src={character.image} alt="" />
</figure>
<h2>{character.name}</h2>
<p>{character.status}</p>
<p>{character.species}</p>
<p>{character.gender}</p>
<p>{character.location.name}</p>
</div>
))}
<h2>{}</h2>
</div>
);
};
export default Characters;
.container
display: flex
flex-wrap: wrap
justify-content: center
.card
padding: 4%
text-align: start
margin: 10px
border-radius: 10px
box-shadow: 1px 1px 9px 1px #1d010125
figure
img
width: 100px
Bueno para agregar el DarkMode y LightMode agrege estas lineas de codigo en el Componente Header.
const Header = () => {
const [mode, setMode] = useState(false)
const onHandleClick= ()=>{
setMode(!mode);
}
if(mode){
document.documentElement.style.setProperty('--background-App','#282c34')
document.documentElement.style.setProperty('--font-color','white')
}else{
document.documentElement.style.setProperty('--background-App','white')
document.documentElement.style.setProperty('--font-color','black')
}
return (
<div className='header'>
<h1>React Hooks</h1>
<button type='button' onClick={onHandleClick} >{mode ? "DarkMode" : "LigthMode"}</button>
</div>
);
}
export default Header
El resultado:
Para usar los atajos de los que habla el profesor, hay que instalar la siguiente extensión, ya que la que puso en los links de apoyo no contiene estos atajos 😃
https://marketplace.visualstudio.com/items?itemName=EQuimper.react-native-react-redux
Creo que falto explicar la funcion del return dentro de un -useEffect-
useEffect(() => {
// aqui se ejecuta las funciones del efecto;
return () => {
//aqui se ejecuta el Desmontaje del Efecto;
// esto es lo que me refiero
}
}, [props.ActualizaEstado])
Les dejo este Link, en el minuto 19:40 empiezan a explicar la funcion del return
https://www.youtube.com/watch?v=kPx2qgDS3ak&list=PLvq-jIkSeTUZ5XcUw8fJPTBKEHEKPMTKk&index=17&t=594s
Les comparto mi solución para el estilizado utilize Semantic UI recomiendo mucho ese Framework
Una peculiaridad de useEffect es que la función que le pasamos (effect) se ejecuta despues del primer render y despues de cada update. Es como si cada efecto perteneciera a un render en particular
No se les olvide colocarle el key al elemento h2 para evitar los warnings en consola.
<h2 key={character.id}>{character.name}</h2>
Usando asincronía a la llamada de la API:
const apiURL = 'https://rickandmortyapi.com/api/character/';
useEffect(() => {
async function fetchCharacters() {
const response = await fetch(apiURL);
const characters = await response.json();
setCharacters(characters.results);
}
fetchCharacters();
}, []);
Resolviendo el reto
Repositorio: https://github.com/zearkiatos/react-hooks-web
Ah caray pensé que haríamos un e-commerce 😅
Reto
import React ,{useState, useEffect}from 'react'
import '../css/characters.css'
const Characters = () => {
const [characters, setCharacters] = useState ([]);
useEffect(() => {
fetch('https://rickandmortyapi.com/api/character/')
.then(response => response.json())
.then(data => setCharacters(data.results));
},[])
return (
<div className='Characters'>
{characters.map(character => (
<div className='Characters-card'>
<img src={character.image} alt={`imagen de ${character.name}`}/>
<h2 className='Characters-title'>{character.name}</h2>
<p className='Characters-paragraph'><b>ID:</b> {character.id}</p>
<p className='Characters-paragraph'><b>Estatus:</b> {character.status}</p>
<p className='Characters-paragraph'><b>Especie:</b> {character.species}</p>
<p className='Characters-paragraph'><b>Genero:</b> {character.gender}</p>
</div>
))}
</div>
);
}
export { Characters }
.Characters{
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto;
gap: 16px;
padding: 24px;
}
.Characters-card{
padding: 4px;
box-shadow: 0px 0px 8px 1px #9e9e9e;
}
.Characters-title{
margin: 8px;
}
.Characters-paragraph{
margin: 0;
}
Gracias a todos los aportes de los companeros 😃 Ahi practicando con Tailwinds
return (
<div className="Characters container px-5 mx-auto">
<div className=" flex flex-wrap -m-2">
{characters.length > 0 && characters.map(character => (
<div className="p-2 lg:w-1/3 md:w-1/2 w-full">
<div className="h-full flex items-center border-gray-200 border p-4 rounded-lg">
<img alt="team" className="w-16 h-16 bg-gray-100 object-cover object-center flex-shrink-0 rounded-full mr-4" src={character.image} />
<div className="flex-grow">
<h2 className="text-900 title-font font-medium">{character.name}</h2>
<p className="text-gray-400">{character.status}</p>
<p className="text-gray-400">{character.species}</p>
</div>
</div>
</div>
))}
</div>
</div>
);
Para instalar sass en React utiliza el siguiente comando:
npm i sass
Para más informacion aqui la pagina oficial:
https://create-react-app.dev/docs/adding-a-sass-stylesheet/
Para aprender un poco más de useEffect
Hay una parte muy importante de este hook llamada cleanup, se utiliza como su nombre lo dice, para limpiar o eliminar las acciones del efecto. No siempre es necesario usarlo, pero es mejor conocerlo a luego tener un problema de optimización grave.
Recomiendo el siguiente artículo para saber un poco más del mismo:
React useEffect cleanup: How and when to use it
Así quedo mi maquetación! tomando un poco el estilo de la web de la API
En App.js
import React, { useState } from 'react';
import Header from './components/Header';
import Characters from './components/Characters';
import './App.css';
function App() {
const [darkMode, setDarkMode] = useState(false);
const handleClick = () => {
setDarkMode(!darkMode);
}
return (
<div className={`App ${darkMode ? 'dark-mode' : 'light-mode'}`}>
<Header handleClick={handleClick} darkMode={darkMode} />
<Characters />
</div>
);
}
export default App;
Header.jsx
import '../assets/styles/components/Header.css';
const Header = props => {
const { handleClick, darkMode } = props
return (
<div className={`header`}>
<h1>ReactHooks</h1>
<button className={`button-mode ${darkMode ? 'light-mode' : 'dark-mode'}`} type="button" onClick={handleClick}>{darkMode ? 'Light mode' : 'Dark mode'}</button>
</div>
);
}
export default Header;
💡 INFO
Función para realizar efectos secundarios.
Se puede pensar como un símil de los métodos del ciclo de vidacomponentDidMount
,componentDidUpdate
ycomponentWillUnmount
combinados, pero sin bloquear el proceso de actualización de la vista.
.
Se puede considerar como efectos secundarios como:
En conjunto, hay 2 tipos de efectos secundarios: los que requieren y no de limpieza.
.
💡INFO
Se dice limpieza/barrido al recurso que necesita, por lógica, encadenar un proceso ya sea por actualización o desmontaje.
.
Ejemplos como:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect
, le comunicamos a React que el componente necesita realizar algo después de un renderizado..
💡INFO
useEffect
se ejecuta en cada primer renderizado y después de cada actualización.
.
Ejemplos como:
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
**useEffect**(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.**subscribeToFriendStatus**(props.friend.id, handleStatusChange);
return function **cleanup**() {
ChatAPI.**unsubscribeFromFriendStatus**(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
useEffect
, cuando se retorna una función, indicamos el modo en que se limpia/barre.cleanup
es de fines prácticos, se debe utilizar arrow functionsreturn () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
💡 INFO
React lanza una limpieza cuando el componente se desmonta o como acción previa a cada siguiente efecto.
.
El API de useEffect
permite un parámetro adicional indicando 2 efectos:
[]
- Si deseamos ejecutar un efecto y limpiarlo una vez, desvinculando la función de los cambios de los props
o state
, por consiguiente estos últimos dentro de la función siempre tendrán sus valores iniciales.[vale]
- Se omite el flujo natural de la función, ejecutándose solamente cuando el valor ha cambiado..
Characters.jsx
import React, { useState, useEffect } from "react";
const Characters = () => {
const [characters, setCharacters] = useState([]);
useEffect(() => {
async function fetchCharacters() {
const response = await fetch("https://rickandmortyapi.com/api/character");
const data = await response.json();
setCharacters(data.results);
}
fetchCharacters();
}, []);
return (
<div className="characters">
{characters.length > 0 &&
characters.map(({ id, name }) => <h2 key={id}>{name}</h2>)}
</div>
);
};
export default Characters;
⚠️ NOTA
Pese que CRA o Create React App incorpora React dinámico para no implementarlo, se sugiere definirlo por estabilidad a nivel componente
Les comparto como quedó mi diseño
Este es el código para implementar el Dark Mode
Anduve haciendolo aplicando mobile first:
Mobile:
Tablet:
Desktop:
Modo oscuro:
Observación: Faltó establecer un key para cada elemento interado.
Nota sobre useEffect
Al pasar como segundo parámetro de useEffect un arreglo vacío quiere decir que useEffect se ejecutará solo cuando se monte el componente, si queremos que se ejecute cada vez que se actualice el componente no pondremos ningún parámetro. Si queremos que se actualice cada vez que algo cambie, dentro del arreglo pondremos dicho parámetro a escuchar, y si queremos hacer algo cuando se desmonte el componente retornaremos esa acción en la función de useEffect.
Comparto mis resultados hasta el momento:
Empezando el curso tome la decision de revisar la documentacion de hooks de react mientras pasaba por cada uno, y realmente fue una decision excelente, les recomiendo leer la doc mientras pasan por cada hook, ademas de aprender como funciona completamente el hook tambien te ofrecen buenas practicas al momento de utilizar lo hooks
De essta manera se puede construir el efecto utilizando async/await. que vuelve el codigo y el manejo de la asincronia muhco mas legible
import { useEffect, useState } from "react";
const Character = (props) => {
const [characters, setCharacters] = useState([]);
useEffect(() => {
const fetchCharacters = async () => {
const response = await fetch("https://rickandmortyapi.com/api/character");
const data = await response.json();
setCharacters(data.results);
};
fetchCharacters();
}, []);
return (
<div className="charachters">
{characters.map((character) => {
return <h2> {character.name} </h2>;
})}
</div>
);
};
export default Character;
Estas clases me han servido para llevar a cabo unas animaciones en mi portfolio 💪
Ahora queda perfeccionarlas y añadirle el Dark Mode 👀
Si quieres ver cómo lo hice, te dejo por aquí el enlace al repo 😄
He de decir que, además de useState y useEffect, tuve que saber algunas cosas acerca del react-router-dom, pero no es muy complicado si lo quieres hacer 😉
Les recomiendo esta lectura de la documentación oficial de React Hooks en español sobre el uso de el hook useEffect . Pensé en resumirla pero es mucho mejor darle una lectura completa para esclarecer cualquier duda.
https://es.reactjs.org/docs/hooks-effect.html
Cumpliendo el reto
Asi me fue…
Aqui mi reto realizado:
LightMode
DarkMode
Muy bueno, por lo general lo que ponía dentro del effect y que actualizaba el state se quedaba en un ciclo infinito de renderizado. ahora veo que es por ese segundo parametro de dicho hooks en donde se pone las variables que escucharán. Y que si se deja vació solo hace el render una vez.
Pude hacer lo del renderizado, pero no lo de darkmode, ya que eso estaba en el Header y no sé como pasar props de hijo a padre (App.js) para luego pasarselo a (Characters.jsx).
¿Alguno sabe?
Así quedó:
Cree un componente “Charater”, me parece que se ve mejor así:
characters.jsx:
import React, { useState, useEffect } from "react";
import Character from './Character'
import './style/characters.css'
const Characters = () => {
const [characters, setCharacters] = useState([]);
useEffect(() => {
fetch("https://rickandmortyapi.com/api/character/")
.then((res) => res.json())
.then((data) => setCharacters(data.results));
}, []);
return (
<div className="characters">
{characters.map((character) => {
return <Character
name={character.name}
status={character.status}
img={character.image}
key={character.id}
/>;
})}
</div>
);
};
export default Characters;
Character.jsx:
import React from 'react'
import './style/character.css'
const Character = ({name,status,img}) => {
return (
<div className="character_container">
<img src={img} alt=""/>
<div className="character_data">
<h2>{name}</h2>
<h2>{status}</h2>
</div>
</div>
)
}
export default Character
Este fue mi resultado:
DarkMode:
HOLA!!!
aquí les dejo mi solución al reto 💚:
async/await
const API =
'https://rickandmortyapi.com/api/character'
const getCharacters = async () => {
const res = await fetch(API)
const { results } = await res.json()
setCharacters(results)
}
useEffect(() => {
getCharacters()
}, [])
Aquí está mi version usando la api de rick y morty e implementando el dark mode
les comparto mi template lo realice lo mejor que pude!!!
Esta sencillo el diseño y me inspire de dribbble
Yo solucione el reto asi:
function cambioFondos(status) {
const back = document.querySelector('.App')
back.style.backgroundColor=status?'#000':'#fff';
const header = document.querySelector('.header');
header.style.backgroundColor=status?'#fff':'rgb(0, 128, 255)';
}
Y la llamamos en el onclick asi:
const handleClick = () =>{
setDarkMode(!darkMode)
cambioFondos(darkMode)
}
Espero y les sirva
Seguimos en el proceso de aprendizaje! ♥
Usando async/await en el useEffect, para que el código luzca más elegante:
useEffect(() =>{
const fetchData = async () => {
const response = await fetch(API_URL).then(res => res.json());
setCharacters(response.results);
}
fetchData();
}, []);
Dark Mode
LIght Mode
Cuando investiguen sobre el hook useEffect
se van a encontrar que se puede retornar
una función para limpiar el efecto.
Esto se refiere a las accion asincronas que modificaran el estado una vez se hayan completado. Si un componente fue destruido antes de que la accion termine. Cuando lo haga tratara de renderizar en un componente que ya no existe por lo que podria dar problemas de rendimiento
En el caso de fetch
y axios
utiliza un objecto llamado AbortController
que abortara la peticion http que se este haciendo cuando el componente se desmonte.
reto:
App.js
import React, { useState } from 'react';
import './App.css';
import Header from './components/Header/Header';
import { Characters } from './components/Characters/Characters';
function App() {
const [darkMode, setDarkMode] = useState(false);
const changeMode = () => {
if (darkMode) {
document.body.classList.add('lightMode');
document.body.classList.remove('darkMode');
} else {
document.body.classList.add('darkMode');
document.body.classList.remove('lightMode');
}
};
return (
<div>
<Header
darkMode={darkMode}
setDarkMode={setDarkMode}
changeMode={changeMode}
/>
<Characters />
</div>
);
}
export default App;
App.css
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
.darkMode {
background-color: #333;
}
.lightMode {
background-color: #eee;
}
Header.jsx
import React, { useState } from 'react';
import './header.css';
const Header = props => {
const { darkMode, setDarkMode, changeMode } = props;
const handleClick = () => {
changeMode();
setDarkMode(!darkMode);
};
return (
<div className='header'>
<h1>Rick & Morty Page</h1>
<button type='button' onClick={handleClick}>
{darkMode ? 'light Mode' : 'Dark Mode'}
</button>
</div>
);
};
export default Header;
RETO
Ligth Mode
DarkMode
Para habilitar el emmet para JSX:
Abrir la configuración de VSCode: Command + , ó Ctrl + ,
asi me quedo el retoo uffff 💪
Tarde pero seguro:
Hice lo mejor que pude
Mi Reto!
Mi tarea:
Muy básico pero funciona.
Este ejercicio me gustó mucho.
|
|
Reto cumplido Oscar.
Light Mode.
Dark Mode
Si quieren revvisar mas a fondo este hook, incluso comparan ciertas configuración para replicar los ciclos de vida de un componente:
https://youtu.be/0ZJgIjIuY7U
Aqui mis resultados!
////////////////
Light Mode
/////////////////
//////////////////
Dark Mode
/////////////////
Mode Light
Mode Dark
Les dejo mi versión aquí.
#Reto
useEffect con async
...
//estado del componente
const [ characters, setCharacters ] = useState([])
// llamado a la API con useEffect
useEffect( ( ) => {
// arrow function con async
const getCharacters = async () => {
//llamado a la API con FECTH API
const res = await Fecth('url_api')
// desestructuro results del objeto devuelto por la API y lo transformo en JSON
const { results } = await res.json()
// actualizo el estado
setCharacters(results)
}
// llamado de la function parallamar a la API
getCharacters()
}, [ ]) // Solo 1 llamado a la API después del primer render)
Soy muy malo diseñando 😅
Hice el reto usando useState, useContext, useEffect y variables de css.
Aun estoy pensando en los colores del dark theme 😁
Algo muy importante a destacar en useEffect es sus segundo argumento. Un arreglo de dependencias que controlan cuando debería ser ejecutado.
Las dependencias son valores definidos fuera del Hook pero son utilizados dentro.
Cabe resaltar que el segundo argumento es opcional y depende su uso React ejecutara el useEffect.
Recomiendo las siguentes lecturas sobre diferencias con el componentDidMount y el infinite-loop
para quitar los Warning de la consola debes agregarle un return al useEffect
useEffect(() => {
fetch('https://rickandmortyapi.com/api/character/')
.then(response => response.json())
.then(data => setCharacteres(data.results))
return
}, [])
y como hicimos un map agregarle el key
return (
<div className="characteres" key="index">
{characters.map(character => (
<h2>{character.name}</h2>
))}
</div>
);
Me gustaría mucho que explicaran por que es buena practica usar return en el useEffect
Yo empece a implementar los stylesd-components, una manera práctica y rapida de dar estilos en React
![](
![](
asi me quedo el codigo
App.js
import React from 'react';
import Header from './components/Header';
import Characters from './components/Characters';
import useDarkMode from './Hooks/useDarkMode';
import './App.css';
function App() {
const [darkMode, setDarkMode] = useDarkMode();
return (
<div className="App" style={darkMode? {backgroundColor: 'black', color: 'white'} : {backgroundColor: 'white'}}>
<Header darkMode={darkMode} setDarkMode={setDarkMode}/>
<Characters darkMode={darkMode} />
</div>
);
}
export default App;
Cree un Hook para manejar el Darkmode
import React, { useState } from 'react';
function useDarkMode() {
const [darkMode, setDarkMode] = useState(false);
return [darkMode, setDarkMode];
}
export default useDarkMode;
Characters.jsx
import React, {useState, useEffect} from 'react';
import styled from 'styled-components';
const Container = styled.div`
background-color: ${props => props.darkMode ? 'black' : 'white'};
color: ${props => props.darkMode ? 'white' : 'black'};
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 20px;
margin: 10px;
`
const Card = styled.div`
height: 100%;
box-shadow: 2px 6px 8px rgba(0,0,0,0.19);
border-radius: 8px;
img {
width: 100%;
border-radius: 8px;
}
h2,h4 {
margin: 0;
margin-bottom: 4px;
}
`
const Characters = ({darkMode}) => {
const [characters, setCharacters] = useState([]);
useEffect(() => {
fetch('https://rickandmortyapi.com/api/character/')
.then(response => response.json())
.then(data => setCharacters(data.results))
}, []);
return (
<Container darkMode={darkMode}>
{
characters.map(character => (
<Card >
<img src={character.image} alt={character.name} />
<div>
<h2>{character.name}</h2>
<h4>{character.status}</h4>
<h4>{character.species}</h4>
<h4>{character.gender}</h4>
</div>
</Card>
))
}
</Container>
)
}
export default Characters;
Header.jsx
import React, { useState } from 'react';
import '../styles/Header.css';
const Header = ({darkMode, setDarkMode}) => {
const handleClick = () => {
setDarkMode(!darkMode);
}
return (
<div className="Header" style={darkMode? {backgroundColor: 'black', color: 'white'} : {backgroundColor: 'white'}}>
<h1>ReactHooks</h1>
<button
style={darkMode? {color: 'white'} : null}
type="button"
onClick={handleClick}>
{darkMode? 'Dark Mode' : 'Light Mode'}
</button>
</div>
)
}
export default Header;
algo de estilo en styles/Header.css
.Header {
display: flex;
justify-content: space-evenly;
}
.Header button {
background-color: transparent;
margin: auto 0;
height: 40px;
width: 120px;
font-size: 15px;
font-weight: bold;
}
React.UseEffect
Ejecuta el código que tengamos adentro justo antes de que React tiene todo listo para renderizar el componente
Creo que es recomendable no escribir la logica de llamado a la api dentro del useeffect, habria que llamar a una función que se encargue de eso.
Disfrutando y aprendiendo hooks! Me encanta que despues de las lecciones hay mini challenges!
import React, { useState, useEffect } from 'react'
const Characters = () => {
const [characters, setCharacters] = useState([]);
useEffect(() => {
fetch("https://rickandmortyapi.com/api/character/")
.then(response => response.json())
.then(data => setCharacters(data.results))
},[]);
return (
<div className="container mt-5">
<div className="row">
{characters.map(character => (
<>
<div className="col-4 mb-5">
<div className="border border-dark p-3">
<img src={ character.image } alt="" />
<h4>{ character.name }</h4>
<h6>{ character.status } - { character.species }<small> ({ character.gender }) </small></h6>
</div>
</div>
</>
))}
</div>
</div>
)
}
export default Characters
Reto cumplido
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?