skip to Main Content

I watn to make Weather App. I just start study react. I do a fetch request to Open Weather API to get a weather data. When i consol.log(data) and update my page, React first return me undefined and after that data. I can’t use data in other components because data is undefined.

App.jsx

function App() {
    const [weatherData, setWeatherData] = useState()
    useEffect(()=>{
        requestWeather('London')
    }, [])
    let requestWeather = async (city)=> {
        try {
            const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=4e4ff6f3165d9a027265ab73068e5a3a&mode=JSON`
            fetch(url)
            .then(data => data.json())
            .then(data => {
                setWeatherData(data)
            })
        } catch (error) {
            console.log(error);
        }
    }
    console.log(weatherData);
    return (
        <>
            <div className="wrapper">
                <Weather weather_data={weatherData}/>
            </div>
        </>
    )
}

Weather.jsx

export default function Weather({weather_data}){
    return(
        <div>{weather_data.name}</div>
        // There '.name' display name of city

    )
}

When i run that i got this errors
ERRORS

2

Answers


  1. No default value was specified for the state:

    const [weatherData, setWeatherData] = useState();
    

    So it defaults to undefined. You could add any default you like. For example, this would default to an empty object:

    const [weatherData, setWeatherData] = useState({});
    

    Or you could not render the Weather component if the value is "falsy":

    <div className="wrapper">
      { weatherData ? <Weather weather_data={weatherData}/> : null }
    </div>
    

    Or you could handle undefined within the Weather component itself:

    <div>{weather_data?.name}</div>
    

    Unrelated, but you’ll also want to get in the habit of terminating statements with semi-colons. JavaScript is forgiving about omitting semi-colons, but programmers should not be. It’s one of those things that will work just fine right up until the moment it doesn’t.

    Login or Signup to reply.
  2. When your component renders it makes an api call to obtain the weather, so untill your call successfully retrieves the weather data and sets it in the state, your weatherData is undefined.

    The solution David provided is also valid.

    My proposal would be to not render your Weather component untill the data is successfully loaded and saved to state like so:

    function App() {
        const [weatherData, setWeatherData] = useState();
        const [isWeatherDataLoading, setIsWeatherDataLoading] = useState(true);
        const [weatherLoadingError, setWeatherLoadingError] = useState(null);
    
        useEffect(() => {
            requestWeather("London");
        }, []);
    
        const requestWeather = (city) => {
            setIsWeatherDataLoading(true);
            setWeatherLoadingError(null);
    
            const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=4e4ff6f3165d9a027265ab73068e5a3a&mode=JSON`;
            fetch(url)
                .then((data) => data.json())
                .then((data) => {
                    setWeatherData(data);
                })
                .catch((error) => {
                    setWeatherLoadingError(JSON.stringify(error));
                })
                .finally(() => {
                    setIsWeatherDataLoading(false);
                });
        };
    
        if (isWeatherDataLoading) {
            return (
                <div className="wrapper">
                    <div>Loading weather</div>
                </div>
            );
        }
    
        if (weatherLoadingError) {
            return (
                <div className="wrapper">
                    <div>Failed to load weather data with error: {weatherLoadingError}</div>
                    <button onClick={() => requestWeather("London")}>Try again</button>
                </div>
            );
        }
    
        return (
            <div className="wrapper">
                <Weather weather_data={weatherData} />
            </div>
        );
    }
    

    In a similar fashion:
    Unrelated, but you’ll also want to get in the habit of handling loading and error states in your React apps. The interviewer might be forgiving, but the user story should not be.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search