API openweathermap.org. Как показывать погоду конкретного города, берущегося из массива?

Вот компонент, отвечающий за запросы на сервер: запрос на сервер

Вот компонент отвечающий за рендер:рендер

Что хочу получить: выбираю город из селектора - соответсвенно рендерится прогноз погоды по этому городу. Вопрос. Какой аргумент мне прописывать в getWeather()? city нельзя это просто весь массив. city[0] тоже, т.к. получает жестко привязанный элемент, мне то надо динамически. И второй вопрос. Как правильно реализовать логику в этом компоненте?

    <div className="search_city">
        <select name="select"> 
            {city.map(item => <option value={item}>{item}</option>)}
        </select>
    </div>

Если я оставляю так, то получается незадействованный "tawn" из useState. В общем не хватает знаний (или я просто сильно туплю), что бы дожать функционал, прошу помощи. p.s. Результат на выходе такой (не смотрите на стили потом доделаю). результат

Температуру, ветер и т.д. разбил на отдельные компоненты, вот пример: введите сюда описание изображения @gaf, получается вот так:

const SearchCity = () => {

const {getWeather} = WeatherServise();

const city = [
    {
      "id": "833",
      "name": "Ḩeşār-e Sefīd"
    },
    {
        "id": '3245',
        "name": "Taglag",
    },
]

const [tawn, setTawn] = useState('Voronezh');

useEffect(() => {
    updateId();
}, [])

const updateId = () => {
    getWeather(tawn)
        .then(onWeatherLoaded)   
} 

const onWeatherLoaded = (e) => {
    setTawn(e.target.value);
}

return (
    <div className="search_city">
        <select value={tawn} onChange = {onWeatherLoaded} name="select"> 
            {city.map(item => <option 
                key = {item.id}>
                {item.name}</option>)}
        </select>
    </div>
)   
}

В консоли получаю ошибку:Cannot read properties of undefined (reading 'value') Плюс я не понимаю куда и зачем мне нужно поднимать состояние, у меня все отрисовывается в этом компоненте


Ответы (1 шт):

Автор решения: gaf

Сначала: Тебе нужно почитать что такое "Контролируемые компоненты" - это ответит сразу на оба вопроса: как подгружать динамически и как правильно реализовать логику.

Потом: tawn - это ответ с данными о погоде. Значит должен его передавать туда, где ты отрисовываешь данные, тебе их надо поднять выше из компонента SearchCity, для этого почитай про "Подъём состояния". В будущем можешь почитать про "Контекст" - это более продвинутый подход к этой задаче.

И наконец: После того, как разберешься со всем предыдущим: тебе не нужно делать запрос getWeather() в Temperature, теперь можешь просто получить данные от родительского компонента через props и отрисовать их.

Обновление в ответ на изменение вопроса:

const SearchCity = () => {

const { getWeather } = WeatherServise();  

const city = [
    {
      "id": "833",
      "name": "Ḩeşār-e Sefīd"
    },
    {
        "id": '3245',
        "name": "Taglag",
    },
]

const [town, setTown] = useState('Taglag') // Это имя текущего города и функция для его обновления. Начальное значение Taglag

useEffect(() => {
    const getWeatherData = async () => {
        const data = await getWeather(town) // Вернется массив с данными о погоде, тебе надо его передать таким компонентам, как: Temperature, чтобы они отрисовывали новые данные       
    }
    getWeatherData()
}, [town]) // <- Запрос выполняем каждый раз, когда пользователь выбирает новый город

const handleChange = (e) => {
    setTown(e.target.value)
}

return (
    <div className="search_city">
        <select value={town} onChange = {handleChange}>  /* Это value значит какое значение сейчас выбрано */ 
            {city.map(item => <option 
                key={item.id}
                value={item.name}  /* Это value значит вариант, который можно выбрать, не забывай указывать */
             >
                {item.name}</option>)}
        </select>
    </div>
    )
}
→ Ссылка