I'm building a weather forecast website with TypeScript and React, but I'm having some trouble to fetch just the cityName.id that I clicked from the first displayed list. When I search a specific city, the API provides a list of cities that contain the name I typed. Please find below what I've done so far:
import { useState, useEffect, ChangeEventHandler, FormEventHandler } from "react"
import { ApiAdvisorVariables } from "../../../variables"
export function ApiAdvisor() {
const [cityName, setCityName] = useState<string>('')
const [value, setValue] = useState<string>('')
const [cityInfo, setCityInfo]: any = useState<{} | null>([])
const [cityWeather, setCityWeather]: any = useState<{} | null>([])
const [cityId, setCityId] = useState<any>(3477)
const handleChange: ChangeEventHandler<HTMLInputElement> = (event: any): void => {
setValue(event.target.value)
}
const handleSubmit: FormEventHandler<HTMLFormElement> = (event: any): void => {
event.preventDefault()
setCityName(value)
}
const handleClick: FormEventHandler<HTMLFormElement> = (): void => {
cityInfo.map((index: any) => {
setCityId(index.id)
console.log(index.id)
})
}
async function getCityId(cityName: string): Promise<any> {
const response = await fetch(`http://apiadvisor.climatempo.com.br/api/v1/locale/city?name=${cityName}&token=${ApiAdvisorVariables.token}`)
const data = await response.json()
console.log(data)
return data
}
async function getCurrentWeather(cityId: string): Promise<any> {
const response = await fetch(`http://apiadvisor.climatempo.com.br/api/v1/weather/locale/${cityId}/current?token=${ApiAdvisorVariables.token}`)
const data = await response.json()
console.log(data)
return data
}
useEffect(() => {
async function fetchData() {
const idInfo = await getCityId(cityName)
const weatherInfo = await getCurrentWeather(cityId)
setCityInfo(idInfo)
setCityWeather(weatherInfo)
}
fetchData()
}, [cityName, cityId])
return (
<section>
<div className="search-container">
<form onClick={handleSubmit}>
<input
onChange={handleChange}
placeholder="Digite o nome da cidade"
/>
<button>Search</button>
</form>
</div>
<div className="weather-info-container">
{cityInfo ? cityInfo.map((index: any, key: string) => {
return (
<form key={key} onClick={handleClick}>
<h2> {index.name}, {index.state} </h2>
</form>
)
}) : ''}
</div>
</section>
);
}
I'm not sure about the cityInfo.map, because I only want to fetch the id from the clicked city, not all of them. Could someone help me?
CodePudding user response:
You can access the id
of an item in a list, from the map()
function like this:
const [cityId, setCityId] = useState<any>(3477)
const handleClick: FormEventHandler<HTMLFormElement> = (id: number): void => { // set up param
setCityId(id)
console.log(id)
}
cityInfo.map((element: any, index: string) => { // <- keep to the naming convention
return (
<form key={element.id} onClick={() => handleClick(element.id)}> <!-- directly pass in the id -->
<h2> {element.name}, {element.state} </h2>
</form>
)
}
The first parameter of map()
function's callback is the individual element/item, the second is the index. And cityInfo.map((index: any, key: string) => {})
is somewhat misleading. So keeping to the naming convention is a good idea. You can refer to Array.prototype.map() MDN docs.
Please also note that, using index
as key is discouraged, you can pass in element.id
as key as well.