1

I am new to React. I want to integrate weatherstack API with my project. Problem is I do not understand how can I input country's capital's name into API's endpoint.

const App = () => {
      const [ countries, setCountries ] = useState([]) 
      const [ searchingItem, setSearchingItem ] = useState('')
      const [ showAll, setShowAll ] = useState(true)
      const [ weatherData, setWeatherData ] = useState([])
      const [ capital, setCapital ] = useState('')
      const api_key = process.env.REACT_APP_WEATHER_API
      
      useEffect(() => {
        axios
          .get('https://restcountries.eu/rest/v2/all')
          .then(response => {
            setCountries(countries.concat(response.data))
          })
      }, [])

      useEffect(() => {
        console.log(capital, searchingItem)
        axios
          .get(`http://api.weatherstack.com/current?access_key=${api_key}&query=${capital}`)
          .then( response => {
            console.log(searchingItem)
            setWeatherData(weatherData.concat(response.data))
          })
          .catch((err) => console.log(err))
      }, [])
      

      const handleChangeSearch = (event) => {
        setSearchingItem(event.target.value)
        setShowAll(false)
        }
  
      let countriesToShow = showAll
          ? countries
          : countries.filter(country => country.name.indexOf(searchingItem) !== -1);

      const handleClick = (country) => {
        setCapital(country.capital)
        setSearchingItem(country.name)
      }


      return (
        <div id='App'>
          <h2>Phonebook</h2>
          <div>
            Search a name <Filter value={searchingItem} onChange={handleChangeSearch} />
            <div>
            { countriesToShow.length === 250 
              ? '' 
              : countriesToShow.length >= 10 
              ? <div><p>Too many matches, specify another filter</p></div> 
              : countriesToShow.length > 1 
              ? countriesToShow.map(country => <div>
                <li key={nanoid()}>{country.name}
                <button type='button' onClick={() => handleClick(country)}>Show</button></li></div>)
              : countriesToShow.length === 1
              ? <div>
                  <View country={countriesToShow[0]} key={nanoid()}/>
                </div>
              : 'No results occured'}
            </div>
            <div>
              <div>{console.log(weatherData)}</div>
            </div>
          </div>
        </div>
      )

I need to display weather data below the View component if I pressed button 'Show'.

I have tried to create state variable capital and set it to country's name whenever onClick event will happen:

const handleChangeSearch = (event) => {
        setSearchingItem(event.target.value)
        setShowAll(false)
        }

But it seems like I can't access to capital variable in the useState hook:

useEffect(() => {
        console.log(capital, searchingItem)
        axios
          .get(`http://api.weatherstack.com/current?access_key=${api_key}&query=${capital}`)
          .then( response => {
            console.log(capital)
            setWeatherData(weatherData.concat(response.data))
          })
          .catch((err) => console.log(err))
      }, [])

because this is the only thing that I am getting when hook makes a call:

error:
code: 601
info: "Please specify a valid location identifier using the query parameter."
type: "missing_query"
__proto__: Object
success: false

Any hints about how to display weather info whenever user clicks Show button?

Here is repo of the project if it is needed: https://github.com/rd9911/UniHelsinkiFullStack/tree/main/part2/part2c

If more info needed please ask.

2 Answers 2

2

When the hook runs initially, capital is empty ''. You want to call the API when capital changes using dep array ([capital]) and avoid calling the API when it is empty. Try this:

 useEffect(() => {
    if(! capital) { return;}

    console.log(capital, searchingItem)
    axios
      .get(`http://api.weatherstack.com/current?access_key=${api_key}&query=${capital}`)
      .then( response => {
        console.log(searchingItem)
        setWeatherData(weatherData.concat(response.data))
      })
      .catch((err) => console.log(err))
  }, [capital])
Sign up to request clarification or add additional context in comments.

Comments

1

When you provide no values inside the second argument(which is an array) of useEffect hook, it will run only once in the beginning. So in your case the call to the API goes even before the capital variable is set. To solve this you can just add capital to the array [capital] as a second argument to useEffect.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.