Правильно ли используется мой эффект использования при получении данных о погоде?

#javascript #node.js #reactjs #api #axios

Вопрос:

 import React,{ useState, useEffect } from 'react'
import axios from 'axios'

const App = () => {

  const [ countries, setCountries ] = useState([])
  const [ search, setSearch ] = useState('')
  const [ weather, setWeather ] = useState({})
  const [ capital, setCapital ] = useState('')

  const api_key = process.env.REACT_APP_API_KEY

  const searchedCountries = countries.filter(country =>
    country.name.common.toLowerCase().includes(search.toLowerCase()))

  useEffect(() => {
    axios
      .get('https://restcountries.com/v3.1/all')
      .then( response => {
        setCountries(response.data)
      })
  },[])

  useEffect(() => {
    const url = `http://api.weatherstack.com/current?access_key=${api_key}amp;query=${capital}`

      axios
      .get(url)
      .then(response => {
        setWeather(response.data)
        console.log('logged weather', response.data)
        console.log('capital inside: ', capital)
      })
    
  },[search])

  console.log(searchedCountries)

  const handleSearch = (event) => {
    setSearch(event.target.value)

    if(searchedCountries.length === 1){
      setCapital(searchedCountries[0].capital[0])
      console.log('capital is set', capital)
    }
    else
      setCapital('')
  }

  const handleShow = (event) => {
    event.preventDefault()
    setSearch(event.target.value)
  }

  if(searchedCountries.length > 10){
    return(
      <>
        <div>
          find countries
          <input value = {search} onChange = {handleSearch} />  
        </div>
        <p>Too many matches, specify another filter</p>
      </>
    )
  }else{
    if(searchedCountries.length === 1){
      const languages = Object.keys(searchedCountries[0].languages)
      console.log(typeof weather, weather)

      return(
        <>
          <div>
            find countries
            <input value = {search} onChange = {handleSearch} />  
          </div>
          <h1>{searchedCountries[0].name.common}</h1>
          <p>capital {searchedCountries[0].capital[0]}</p>
          <p>population {searchedCountries[0].population}</p>
          <h2>languages</h2>
          <ul>
            {languages.map(language => 
              <li key = {language}>{searchedCountries[0].languages[language]}</li>)}
          </ul>
          <img src= {searchedCountries[0].flags.png} alt= 'flag' />
          <h2>Weather in {searchedCountries[0].capital[0]}</h2>
          {/* <p><strong>temperature: </strong> {weather.current.temperature}  Celcius</p> */}
        </>
      )
    }else{
      return(
        <>
          <div>
            find countries
            <input value = {search} onChange = {handleSearch} />  
          </div>
          {searchedCountries.map( (country, index) => {
            return(
              <div key = {country.name.official}>{country.name.common}
                <button onClick = {handleShow} value = {country.name.common} >show</button>
              </div>
            )
          })}

        </>
      )
    }
  }
}

export default App
 

Например:
Я набрал «fin»,
Fin вводится при вводе в поиск
Объект по-прежнему пуст.
После ввода «finl»,
Finl-это тип при вводе в поиск
Переменная погоды содержит данные о погоде в Хельсинки.(Мое ежемесячное использование достигло своего предела, поэтому погода.успех примера изображения имеет значение false.

Если я раскомментировал прокомментированную строку в своем коде, приложение выйдет из строя после того, как вы введете «fin».

Я хочу использовать данные в API погоды для этого приложения, не сталкиваясь с ошибками.

Можете ли вы помочь мне в решении этой проблемы. Я начинающий программист, изучающий react и взаимодействие react с API.

Спасибо вам за ваше понимание.

Ответ №1:

Вопрос

weather является пустым объектом при первоначальном рендеринге:

 const [ weather, setWeather ] = useState({});
 

Таким образом, попытка более глубокого доступа к объекту приведет к ошибке.

Пример:

 weather                     // {}
weather.current             // undefined
weather.current.temperature // error, cannot access X of undefined
 

Решение

  1. Вы можете либо указать допустимое начальное начальное состояние для того, к чему вы обращаетесь, чтобы при неопределенных/нулевых обращениях не возникала ошибка:
      const [ weather, setWeather ] = useState({ current: {} });
     

    Обратите внимание, что вам все равно может потребоваться выполнить следующее, чтобы убедиться, что у вас нет неопределенных/нулевых доступов при любом последующем рендеринге.

  2. Используйте необязательные предложения цепочки/защиты для защиты от неопределенных/нулевых обращений.
    • Дополнительная Цепочка: weather?.current?.temperature
    • Охранные положения: weather amp;amp; weather.current amp;amp; weather.current.temperature

Комментарии:

1. Кроме того, другая проблема заключается в том, что ввод, по-видимому, является задержкой в одном символе. это почему?

2. Обновления состояния реакции @spademarck обрабатываются асинхронно. Если вы регистрируете состояние сразу после его постановки в очередь, вы увидите состояние без обновления.

3. Что я могу сделать, чтобы избавиться от этой задержки? Будет ли лучше, если я не буду использовать useState для своих переменных?

4. @spademarck, какой ввод/состояние задерживается? Я снова изучаю ваш код и пытаюсь понять, почему у вас есть и search состояние, и capital состояние. search является зависимостью для useEffect крючка, но на нее нет ссылки, и вместо capital этого она используется в запросе GET. Можете ли вы уточнить, о чем конкретно вы говорите?

5. У меня есть поиск, чтобы захватить значение входного элемента, и капитал, чтобы иметь значение основного значения для URL-адреса во втором эффекте использования.