简体   繁体   中英

How to stop a React App breaking on refreshing when using UseEffect

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

const Singlecountry = ({searchedCountries, setWeather, weather}) => {
  const weatherName = searchedCountries[0].capital
  const iconname = () => {
    if (weather === undefined) {
      return null
    }
     weather.map(w => w.weather[0].icon)
  }
  console.log(iconname)
  useEffect(() => {
 

    axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${weatherName}&appid=${process.env.REACT_APP_API_KEY}`)
      .then(response => {
        const apiResponse = response.data;
        console.log(apiResponse)
        console.log(`Current temperature in ${apiResponse.name} is ${apiResponse.main.temp - 273.15}℃`);
    setWeather([apiResponse])
      }).catch(error => {
        console.log(error);
    })
  }, [])
  
  return(
  <div>
  capital: {searchedCountries.map(c => <p>{c.capital}</p>)}
  area: {searchedCountries.map(c => <p>{c.area}</p>)}
  <h2>Languages</h2>
  <ul>
  {
    searchedCountries.map(c =>
      
        <ul>
          {Object.values(c.languages).map(l => <li>{l}</li>)}
        </ul>
     
    )
  }
</ul>
  {searchedCountries.map(c => <img src={Object.values(c.flags)[0]} alt="" /> )}
  <h3>Weather</h3>
  <p>temperature is {weather.map(w => w.main.temp - 273.15)} degrees Celsius</p>
<p>wind is {weather.map(w => w.wind.speed)} miles per hour</p>
<img src={`http://openweathermap.org/img/wn/${iconname}.png`} alt="" />

        </div>
  )
}

const Countries = ({ searchedCountries, handleClick, show, setWeather, setCountries, weather}) => {
  if (weather === undefined) {
    return null
  }
  if (searchedCountries.length >= 10) {
    return (
      <div>
        <p>too many countries to list, please narrow your search</p>
      </div>
    )
  } 
  if (searchedCountries.length === 1) {
    return (
 <Singlecountry searchedCountries={searchedCountries} setWeather={setWeather} weather={weather}/>
    )
  }
  if (show === true) {
    return (
      <Singlecountry searchedCountries={searchedCountries} setWeather={setWeather} />
    )
  }
  return (
    <ul>
    {searchedCountries.map(c => <li>{c.name.common}<button onClick={handleClick} >show</button></li>)}
  </ul>
  )
}


const App = () => {
const [countries, setCountries] = useState([])
const [newSearch, setNewSearch] = useState('')
const [show, setShow] = useState(false)
const [weather, setWeather] = useState('')


const handleSearchChange = (event) => {
  setNewSearch(event.target.value)
}

const handleClick = () => {
 setShow(!show)
}

const searchedCountries = 
countries.filter(c => c.name.common.includes(newSearch))

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


  return (
    <div>
<div><p>find countries</p><input value={newSearch} onChange={handleSearchChange} /></div>
<div>
  <h2>countries</h2>
  <Countries searchedCountries={searchedCountries} handleClick={handleClick} show={show} setCountries={setCountries} setWeather={setWeather} weather={weather}/>
</div>
    </div>
  )
}


export default App

The following code is designed to display information on countries when the user types in the countries' name in the search bar, including capital city, temperature and its weather.

The app fetches country data from a Countries API and when the user searches for a specific country, the weather its then fetched from a Weather API.

However, when the app is refreshed, the app breaks when searching for an individual country's weather.

Does anyone know why this is and how to solve it?

Thanks

It looks like you're using axios inside useEffect which can cause and infinite loop and crash your app. I recommend creating a separate function for your data fetching and then call the function in the useEffect like so:

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

useEffect(() => {
 fetchCountries()
}, [fetchCountries])

The key is the dependency array in useEffect which will only update if there is a change in the list of countries from fetchCountries function, thus preventing the infinite loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM