Trädvy Permalänk
Medlem
Plats
Gävle
Registrerad
Sep 2005

React api och promise

Jag har suttit och försökt lösa det här problemet i flera timmar nu men fattar inte vad som är fel. Jag har kollat att jag får rätt objekt med console.log. Men programmet crachar när jag försöker sätta <h2> rubriken längst ner och det är själva tempen som är undefined vid det ögonblicket.

Jag fattar att anropet sker asynkront och att weather.current.temp_c inte hunnit få något värde än. Men jag förstår inte hur jag ska lösa problemet. Någon som har något tips till mig?

import React, { useState, useEffect } from 'react' import axios from 'axios' const Weather = ({ capital }) => { const [weather, setWeather] = useState([]) const getWeatherData = () => { axios.get('http://api.apixu.com/v1/current.json?key=...' + capital) .then(response => { setWeather(response.data) }) } useEffect(getWeatherData, []) return ( <h2>Weather in {capital} temp:{weather.current.temp_c}</h2> ) } export default Weather

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2013
Skrivet av burton666:

Jag har suttit och försökt lösa det här problemet i flera timmar nu men fattar inte vad som är fel. Jag har kollat att jag får rätt objekt med console.log. Men programmet crachar när jag försöker sätta <h2> rubriken längst ner och det är själva tempen som är undefined vid det ögonblicket.

Jag fattar att anropet sker asynkront och att weather.current.temp_c inte hunnit få något värde än. Men jag förstår inte hur jag ska lösa problemet. Någon som har något tips till mig?

import React, { useState, useEffect } from 'react' import axios from 'axios' const Weather = ({ capital }) => { const [weather, setWeather] = useState([]) const getWeatherData = () => { axios.get('http://api.apixu.com/v1/current.json?key=...' + capital) .then(response => { setWeather(response.data) }) } useEffect(getWeatherData, []) return ( <h2>Weather in {capital} temp:{weather.current.temp_c}</h2> ) } export default Weather

Du passar bara in din funktion som en referens i useEffect, du måste invoka den.

useEffect(() => getWeatherData(), []);

Annars vid asynkrona anropt brukar man kunna visa en loading spinner eller dylikt tills att datan hämtats.
Den kommer köra rendern först och då visas loaden, sen då datan kommer in kommer komponenten renderas om och då visas datan.

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jul 2011
Skrivet av burton666:

Jag har suttit och försökt lösa det här problemet i flera timmar nu men fattar inte vad som är fel. Jag har kollat att jag får rätt objekt med console.log. Men programmet crachar när jag försöker sätta <h2> rubriken längst ner och det är själva tempen som är undefined vid det ögonblicket.

Jag fattar att anropet sker asynkront och att weather.current.temp_c inte hunnit få något värde än. Men jag förstår inte hur jag ska lösa problemet. Någon som har något tips till mig?

import React, { useState, useEffect } from 'react' import axios from 'axios' const Weather = ({ capital }) => { const [weather, setWeather] = useState([]) const getWeatherData = () => { axios.get('http://api.apixu.com/v1/current.json?key=...' + capital) .then(response => { setWeather(response.data) }) } useEffect(getWeatherData, []) return ( <h2>Weather in {capital} temp:{weather.current.temp_c}</h2> ) } export default Weather

Du borde nog inte sätta ett initialt värde på setState, utan lämna funktionen utan parametrar, då har den värdet undefined tills du sätter den. Senare längre ner innan du renderar din header kan du kolla om weather är undefined, och då skriva ut att den laddar, eller bara null för att ha den blank.
Sen kan du även passa in capital i listan vid useEffect, då får du uppdatering på väder när du byter stad.

Får väl se om min semesterhjärna inte missminner helt hur man gör saker ☺️

Skickades från m.sweclockers.com

NZXT Phantom 410 (Vit) | i5 3570k@4.2GHz | Asus P8Z77-V LE | Corsair Vengeance LP 1600MHz 16GB | Gigabyte GTX 670 Windforce OC @1GHz | Seagate 600 480GB | Corsair HX750 | Cooler Master 212 Evo

Trädvy Permalänk
Medlem
Plats
Gävle
Registrerad
Sep 2005

@zaibuf: tackar för tipset, men det blev ingen skillnad
@Cheesier: jag provade att ditt tips och använde en ternary vid renderingen och det fungerade perfekt.

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jul 2011
Skrivet av zaibuf:

Du passar bara in din funktion som en referens i useEffect, du måste invoka den.

useEffect(() => getWeatherData(), []);

Annars vid asynkrona anropt brukar man kunna visa en loading spinner eller dylikt tills att datan hämtats.
Den kommer köra rendern först och då visas loaden, sen då datan kommer in kommer komponenten renderas om och då visas datan.

Detta stämmer väl inte riktigt? Man vill ju passa in en referens till en funktion bara, så får react köra den senare. Det du gör i din kod är att passa in en ny funktion som bara kallar på den andra funktionen.

Skickades från m.sweclockers.com

NZXT Phantom 410 (Vit) | i5 3570k@4.2GHz | Asus P8Z77-V LE | Corsair Vengeance LP 1600MHz 16GB | Gigabyte GTX 670 Windforce OC @1GHz | Seagate 600 480GB | Corsair HX750 | Cooler Master 212 Evo

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2013
Skrivet av Cheesier:

Detta stämmer väl inte riktigt? Man vill ju passa in en referens till en funktion bara, så får react köra den senare. Det du gör i din kod är att passa in en ny funktion som bara kallar på den andra funktionen.

Skickades från m.sweclockers.com

Utgick från svaret från stackoverflow, har själv inte använt mig av hooks utan jag kör mest Redux och traditionellt med lifecycle methods. Här är länken till stackoverflow
Men svaret verkar vara hur man hanterar async functions i useEffect, vilket inte var det som efterfrågades här.

Trädvy Permalänk
Medlem
Registrerad
Jul 2017

https://jsfiddle.net/ucvpbgho/

Ersätt med din egen API key.