Desarrollar un dashboard interactivo y visualmente intuitivo utilizando tecnologías web modernas, como React, que permita a los usuarios monitorear en tiempo real métricas clave del clima.
En el componente src/App.tsx, agregue:
{/* Hooks */ }
import { useEffect } from 'react';
{/* Hooks */ }
...
interface Indicator {
title?: String;
subtitle?: String;
value?: String;
}
function App() { ... }
fase
de Montaje en el ciclo de vida
) en el DOM. ...
function App() {
{/* Hook: useEffect */}
useEffect( ()=>{}, [] )
return ( ... )
}
En el hook useEffect del componente src/App.tsx
function App() {
{/* Hook: useEffect */}
useEffect(()=>{
let request = async () => { }
request();
},[])
return ( ... )
}
function App() {
{/* Hook: useEffect */}
useEffect(()=>{
let request = async () => {
{/* Request */}
let API_KEY = "OPENWEATHERMAP' API KEY"
let response = await fetch(`https://api.openweathermap.org/data/2.5/forecast?q=Guayaquil&mode=xml&appid=${API_KEY}`)
let savedTextXML = await response.text();
}
request();
},[])
return ( ... )
}
parser
) de XML function App() {
{/* Hook: useEffect */}
useEffect(()=>{
let request = async () => {
{/* Request */}
...
{/* XML Parser */}
const parser = new DOMParser();
const xml = parser.parseFromString(savedTextXML, "application/xml");
}
request();
},[])
return ( ... )
}
function App() {
{/* Hook: useEffect */}
useEffect(()=>{
let request = async () => {
...
{/* XML Parser */}
...
{/* Arreglo para agregar los resultados */}
let dataToIndicators : Indicator[] = new Array<Indicator>();
{/*
Análisis, extracción y almacenamiento del contenido del XML
en el arreglo de resultados
*/}
let name = xml.getElementsByTagName("name")[0].innerHTML || ""
dataToIndicators.push({"title":"Location", "subtitle": "City", "value": name})
let location = xml.getElementsByTagName("location")[1]
let latitude = location.getAttribute("latitude") || ""
dataToIndicators.push({ "title": "Location", "subtitle": "Latitude", "value": latitude })
let longitude = location.getAttribute("longitude") || ""
dataToIndicators.push({ "title": "Location", "subtitle": "Longitude", "value": longitude })
let altitude = location.getAttribute("altitude") || ""
dataToIndicators.push({ "title": "Location", "subtitle": "Altitude", "value": altitude })
console.log( dataToIndicators )
}
request();
},[])
return ( ... )
}
(STOP 1) Compruebe el resultado en el navegador.
En el componente src/App.tsx, agregue:
import { useEffect, useState } from 'react';
function App() {
{/* Variable de estado y función de actualización */}
let [indicators, setIndicators] = useState<Indicator[]>([])
{/* Hook: useEffect */}
...
return ( ... )
}
En el hook useEffect del componente src/App.tsx, modifique la variable de estado mediante la función de actualización.
function App() {
{/* Hook: useEffect */}
useEffect(()=>{
let request = async () => {
...
// console.log( dataToIndicators )
{/* Modificación de la variable de estado mediante la función de actualización */}
setIndicators( dataToIndicators )
}
request()
},[])
return ( ... )
}
Agregue la función renderIndicators encargada de iterar la variable de estado indicators usando la plantilla de elementos <Grid>
e <IndicatorWeather>
function App() {
{/* Hook: useEffect */}
useEffect(()=>{ ... },[])
let renderIndicators = () => {
return indicators
.map(
(indicator, idx) => (
<Grid key={idx} size={{ xs: 12, xl: 3 }}>
<IndicatorWeather
title={indicator["title"]}
subtitle={indicator["subtitle"]}
value={indicator["value"]} />
</Grid>
)
)
}
{/* JSX */}
return ( ... )
}
En el componente src/App.tsx:
...
function App() {
...
{/* JSX */}
return (
<Grid container spacing={5}>
{/* Indicadores */}
{/* <Grid size=> ... </Grid> */}
{renderIndicators()}
</Grid>
...
)
}
(STOP 2) Compruebe el resultado en el navegador.
En el componente src/App.tsx, agregue:
function App() {
{/* Variable de estado y función de actualización */}
let [indicators, setIndicators] = useState<Indicator[]>([])
let [owm, setOWM] = useState(localStorage.getItem("openWeatherMap"))
{/* Hook: useEffect */}
...
return ( ... )
}
En el hook useEffect del componente src/App.tsx, agregue:
openWeatherMap
y expiringTime
...
function App() {
{/* Hook: useEffect */}
useEffect(() => {
let request = async () => {
{/* Referencia a las claves del LocalStorage: openWeatherMap y expiringTime */}
let savedTextXML = localStorage.getItem("openWeatherMap") || "";
let expiringTime = localStorage.getItem("expiringTime");
{/* Request */}
...
{/* XML Parser */}
...
}
request();
}, [])
}
...
function App() {
{/* Hook: useEffect */}
useEffect(() => {
let request = async () => {
{/* Referencia a las claves del LocalStorage: openWeatherMap y expiringTime */}
...
{/* Obtenga la estampa de tiempo actual */}
let nowTime = (new Date()).getTime();
{/* Request */}
...
{/* XML Parser */}
...
}
request();
}, [])
}
expiringTime
o si la estampa de tiempo actual supera el tiempo de expiración para realizar la petición asincrónica ...
function App() {
{/* Hook: useEffect */}
useEffect(() => {
let request = async () => {
{/* Referencia a las claves del LocalStorage: openWeatherMap y expiringTime */}
...
{/* Obtenga la estampa de tiempo actual */}
...
{/* Verifique si es que no existe la clave expiringTime o si la estampa de tiempo actual supera el tiempo de expiración */}
if(expiringTime === null || nowTime > parseInt(expiringTime)) {
{/* Request */}
...
}
{/* XML Parser */}
...
}
request();
}, [])
}
...
function App() {
{/* Hook: useEffect */}
useEffect(() => {
let request = async () => {
{/* Referencia a las claves del LocalStorage: openWeatherMap y expiringTime */}
...
{/* Obtenga la estampa de tiempo actual */}
...
{/* Verifique si es que no existe la clave expiringTime o si la estampa de tiempo actual supera el tiempo de expiración */}
if(expiringTime === null || nowTime > parseInt(expiringTime)) {
{/* Request */}
...
{/* Tiempo de expiración */}
let hours = 0.01
let delay = hours * 3600000
let expiringTime = nowTime + delay
{/* En el LocalStorage, almacene el texto en la clave openWeatherMap, estampa actual y estampa de tiempo de expiración */}
localStorage.setItem("openWeatherMap", savedTextXML)
localStorage.setItem("expiringTime", expiringTime.toString())
localStorage.setItem("nowTime", nowTime.toString())
{/* DateTime */}
localStorage.setItem("expiringDateTime", new Date(expiringTime).toString())
localStorage.setItem("nowDateTime", new Date(nowTime).toString())
{/* Modificación de la variable de estado mediante la función de actualización */ }
setOWM( savedTextXML )
}
{/* XML Parser */}
...
}
request();
}, [])
}
...
function App() {
{/* Hook: useEffect */}
useEffect(() => {
let request = async () => {
{/* Referencia a las claves del LocalStorage: openWeatherMap y expiringTime */}
...
{/* Obtenga la estampa de tiempo actual */}
...
{/* Verifique si es que no existe la clave expiringTime o si la estampa de tiempo actual supera el tiempo de expiración */}
if(expiringTime === null || nowTime > parseInt(expiringTime)) {
...
}
{/* Valide el procesamiento con el valor de savedTextXML */}
if( savedTextXML ) {
{/* XML Parser */}
{/* Arreglo para agregar los resultados */ }
{/*
Análisis, extracción y almacenamiento del contenido del XML
en el arreglo de resultados
*/}
{/* Modificación de la variable de estado mediante la función de actualización */ }
}
}
request();
}, [])
}
...
function App() {
{/* Hook: useEffect */}
useEffect(() => {
let request = async () => {
...
}
request();
}, [owm])
}
3️⃣ React Lifecycle
— Pratham (@Prathkum) March 19, 2021
- Interactive React Lifecycle Methods diagram.
🔗 https://t.co/7UVoA1rXCZ pic.twitter.com/ZcicnZauXC
⚛️ useEffect cheatsheet ↓
— George Moller (@_georgemoller) October 17, 2023
❌ Thinking of useEffect as a lifecycle method.
✅ Thinking of useEffect as a mechanism to sync data (state/props) with systems that aren’t controlled by React. pic.twitter.com/v8BK5CLsSn
React Lifecycle, React Lifecycle phases, parser