Estoy enfrentando el error TypeError: Cannot read properties of undefined (reading 'map')
Este código debería devolver el nombre de la ciudad en un título de tarjeta que está definido en mi otro archivo pero arroja un error.
Códigos:
import React, {Component} from 'react'; import Body from './Body'; class Weather extends Component { constructor(props) { super(props); this.state = { weather: [], }; } async componentDidMount() { const url = `http://api.weatherapi.com/v1/current.json?key=${this.props.api}&q=Jaipur&aqi=no`; let data = await fetch(url); let parsedData = await data.json(); this.setState({ weather: parsedData.weather, }); } render() { return ( <div className="container"> <div className="row"> {this.state.weather.map((element) => { return ( <div className="col-md-4"> <Body city={element.location.name} /> </div> ); })} </div> </div> ); } } export default Weather; su matriz meteorológica está vacía antes de la llamada a la API, por lo que usar this.state.weather.map provocará el error.
Hay dos cosas importantes antes de usar el map con arreglos :
verifique su declaración/definición mediante una simple declaración if :
{ if(myArrayOfData) { myArrayOfData.map( // rest of the codes ... ) } } O con el uso ? abreviado de if
{ myArrayOfData?.map( // rest of the codes ... ) } verifique el contenido de la matriz y use la función de map después de verificar su longitud (que le indica que los datos llegaron de la llamada API, etc. y están listos para procesar)
{ if(myArrayOfData) { if(myArrayOfData.length > 0) { myArrayOfData.map( // rest of the codes ... ) } } } Si bien el fragmento anterior funciona correctamente, puede simplificarlo al verificar ambas condiciones if juntas:
{ if(myArrayOfData?.length > 0) { myArrayOfData.map( // rest of the codes ... ) } } Entonces, simplemente haga algunos cambios en el retorno del componente Weather :
<div className="row"> { if(this.state.weather?.length > 0) { this.state.weather.map((element) => { return ( <div className="col-md-4" key={element.id}> // also don't forget about the passing a unique value as key property <Body city={element.location.name}/> </div> ); }) } } </div>En ejemplos del mundo real, es posible que deba mostrar algunos componentes de carga mientras se obtienen los datos.
{ if(myArrayOfData?.length > 0) { myArrayOfData.map( // rest of the codes ... ) } else { <Loading /> } } const anEmptyArray = [] if(anEmptyArray){ // rest of the codes ... } El resultado de la comparación en if(anEmptyArray) siempre es true con una matriz vacía.
Supongamos que parsedData.weather tiene el tipo de datos correcto. Debe hacer una lógica condicional, para verificar this.state.weather debe tener un valor de API.
aquí hay un ejemplo
render() { const { weather } = this.state; // Access the state `weather` return ( <> <div className="container"> <div className="row"> { /* This way use conditional ternary operator */ } {weather.length ? weather.map((element) => { return ( <div className="col-md-4"> <Body city={element.location.name}/> </div> ); }) : <span>Loading...</span>} </div> </div> </> ); }