Revise el diagrama interactivo de los hooks en el ciclo de vida de los componentes.
Fuente: React Hooks Lifecycle Diagram
En el componente App.tsx
, agregue la referencia al hook useEffect.
import { useEffect } from 'react';
...
En el componente App.tsx
, agregue el hook useEffect para reaccionar después del primer renderizado ( fase
de Montaje en el ciclo de vida
) en el DOM.
function App() {
{/* Variable de estado y función de actualización */}
...
{/* Hook: useEffect */}
{/* Función para el efecto secundario a ejecutar y Arreglo de dependencias */}
useEffect( ()=>{}, [] )
...
}
En el hook useEffect del componente App.tsx
...
{/* Hook: useEffect */}
useEffect(()=>{
(async ()=>{ })()
},[])
...
...
{/* Hook: useEffect */}
useEffect(()=>{
(async ()=>{
{/* Request */}
let API_KEY = "AQUÍ VA SU API KEY DE OPENWEATHERMAP"
let response = await fetch(`https://api.openweathermap.org/data/2.5/forecast?q=Guayaquil&mode=xml&appid=${API_KEY}`)
let savedTextXML = await response.text();
})()
},[])
...
parser
) de XML ...
{/* Hook: useEffect */}
useEffect(()=>{
(async ()=>{
{/* Request */}
...
{/* XML Parser */}
const parser = new DOMParser();
const xml = parser.parseFromString(savedTextXML, "application/xml");
})()
},[])
...
...
{/* Hook: useEffect */}
useEffect(()=>{
(async ()=>{
...
{/* XML Parser */}
...
{/* Arreglo para agregar los resultados */}
let dataToIndicators = new Array()
{/*
Análisis, extracción y almacenamiento del contenido del XML
en el arreglo de resultados
*/}
let location = xml.getElementsByTagName("location")[1]
let geobaseid = location.getAttribute("geobaseid")
dataToIndicators.push(["Location","geobaseid", geobaseid])
let latitude = location.getAttribute("latitude")
dataToIndicators.push(["Location","Latitude", latitude])
let longitude = location.getAttribute("longitude")
dataToIndicators.push(["Location","Longitude", longitude])
console.log( dataToIndicators )
})()
},[])
...
(STOP 1) Compruebe el resultado en el navegador.
En el componente App.tsx
, agregue la referencia al hook useState.
import { useEffect, useState } from 'react';
...
En el componente App.tsx
, agregue la variable de estado indicators y la función de actualización setIndicators. El valor predeterminado de la variable de estado es un arreglo vacío.
function App() {
{/* Variable de estado y función de actualización */}
let [indicators, setIndicators] = useState([])
...
{/* Hook: useEffect */}
...
}
En el hook useEffect del componente App.tsx
, renderice el arreglo temporal en un arreglo de elementos <Indicator>
y modifique la variable de estado mediante la función de actualización.
...
{/* Hook: useEffect */}
useEffect(()=>{
(async ()=>{
...
{/*
Análisis, extracción y almacenamiento del contenido del XML
en el arreglo de resultados
*/}
...
// console.log( dataToIndicators )
...
{/* Renderice el arreglo de resultados en un arreglo de elementos Indicator */}
let indicatorsElements = Array.from(dataToIndicators).map(
(element) => <Indicator title={element[0]} subtitle={element[1]} value={element[2]} />
)
{/* Modificación de la variable de estado mediante la función de actualización */}
setIndicators(indicatorsElements)
})()
},[])
...
En el JSX del componente App.tsx
, cambie los elementos Indicator por elementos de la variable de estado.
...
function App() {
{/* JSX */}
return (
<Grid container spacing={5}>
<Grid xs={6} lg={2}>
{indicators[0]}
{/* <Indicator title='Precipitación' subtitle='Probabilidad' value={0.13} /> */}
</Grid>
<Grid xs={6} lg={2}>
{indicators[1]}
{/* <Indicator title='Precipitación' subtitle='Probabilidad' value={0.13} /> */}
</Grid>
<Grid xs={6} lg={2}>
{indicators[2]}
{/* <Indicator title='Precipitación' subtitle='Probabilidad' value={0.13} /> */}
</Grid>
...
</Grid>
)
}
(STOP 2) Compruebe el resultado en el navegador.
En el hook useEffect del componente App.tsx
, reorganice el código para usar el almacenamiento del navegador (LocalStorage
) para guardar la respuesta de la petición asincrónica.
...
{/* Hook: useEffect */}
useEffect(()=>{
(async ()=>{
{/* 1. Comente el código anterior con el Request */}
// {/* Request */ }
// let API_KEY = "AQUÍ VA SU API KEY DE OPENWEATHERMAP"
// let response = await fetch(`https://api.openweathermap.org/data/2.5/forecast?q=Guayaquil&mode=xml&appid=${API_KEY}`)
// let savedTextXML = await response.text();
{/* 2. Del LocalStorage, obtiene el valor de las claves openWeatherMap y expiringTime */}
let savedTextXML = localStorage.getItem("openWeatherMap")
let expiringTime = localStorage.getItem("expiringTime")
{/* 3. Obtenga la estampa de tiempo actual */}
let nowTime = (new Date()).getTime();
{/* 4. Realiza la petición asicrónica cuando:
(1) La estampa de tiempo de expiración (expiringTime) es nula, o
(2) La estampa de tiempo actual es mayor al tiempo de expiración */}
if(expiringTime === null || nowTime > parseInt(expiringTime)) {
{/* 5. Request */}
let API_KEY = "AQUÍ VA SU API KEY DE OPENWEATHERMAP"
let response = await fetch(`https://api.openweathermap.org/data/2.5/forecast?q=Guayaquil&mode=xml&appid=${API_KEY}`)
savedTextXML = await response.text();
{/* 6. Diferencia de tiempo */}
let hours = 1
let delay = hours * 3600000
{/* 7. En el LocalStorage, almacena texto en la clave openWeatherMap y la estampa de tiempo de expiración */}
localStorage.setItem("openWeatherMap", savedTextXML)
localStorage.setItem("expiringTime", (nowTime + delay ).toString() )
}
{/* XML Parser */}
...
{/* Arreglo para agregar los resultados */}
...
})()
},[])
...
(STOP 3) Compruebe el resultado en el navegador.
Defina:
[{ ... }, { ... }]
.En el componente App.tsx
:
NOTA: Revise los comentarios numerados y adáptelos al código de su componente
function App() {
{/*
1. Agregue la variable de estado (dataTable) y función de actualización (setDataTable).
*/}
let [rowsTable, setRowsTable] = useState([])
...
useEffect(()=>{
(async ()=>{
...
{/* Modificación de la variable de estado mediante la función de actualización */}
...
{/*
2. Procese los resultados de acuerdo con el diseño anterior.
Revise la estructura del documento XML para extraer los datos necesarios.
*/}
let arrayObjects = Array.from( xml.getElementsByTagName("time") ).map( (timeElement) => {
let rangeHours = timeElement.getAttribute("from").split("T")[1] + " - " + timeElement.getAttribute("to").split("T")[1]
let windDirection = timeElement.getElementsByTagName("windDirection")[0].getAttribute("deg") + " "+ timeElement.getElementsByTagName("windDirection")[0].getAttribute("code")
return { "rangeHours": rangeHours,"windDirection": windDirection }
})
arrayObjects = arrayObjects.slice(0,8)
{/* 3. Actualice de la variable de estado mediante la función de actualización */}
setRowsTable(arrayObjects)
})()
},[])
...
return (
...
<Grid xs={12} lg={8}>
{/* 4. Envíe la variable de estado (dataTable) como prop (input) del componente (BasicTable) */}
<BasicTable rows={rowsTable}></BasicTable>
</Grid>
...
)
}
En el componente BasicTable.tsx
.
NOTA: Revise los comentarios numerados y adáptelos al código de su componente
{/* 1. Importe los hooks de estado y ejecución en segundo plano (useState y useEffect) */}
import { useState, useEffect } from 'react';
{/* 2. Comente la funciones de procesamiento de datos (createData) y las variables con valores fijos (rows) */}
/*
function createData(
...
}
*/
/*
const rows = [
...
];
*/
{/* 3. Declare la interfaz del prop de entrada */}
interface Config {
rows: Array<object>;
}
export default function BasicTable( data:Config ) {
{/*
4. Declare la variable de estado (rows) y la función de actualización (setRows).
Use el mismo identificador de la variable con valores fijos (rows)
*/}
let [rows, setRows] = useState([])
{/*
5. Agregue el hook useEffect, controlado por el prop del componente (data), y
Dentro del hook, invoque al métdo de actualización con el valor del prop (data.rows).
*/}
useEffect( () => {
(()=> {
setRows(data.rows)
})()
}, [data] )
{/* JSX */}
return (
...
{/* Modifique la cabecera de la tabla con los títulos adecuados */}
<TableCell>Rango de horas</TableCell>
<TableCell align="right">Dirección del viento</TableCell>
...
{/* Modifique las filas de la tabla con las claves rangeHours y windDirection del objeto */}
{rows.map((row) => (
<TableRow
key={row.rangeHours}
...
>
<TableCell component="th" scope="row">
{row.rangeHours}
</TableCell>
<TableCell align="right">{row.windDirection}</TableCell>
</TableRow>
))}
...
)
}
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