Reputation: 41
I try to call two functions in my useEffect hook
import React, { useState, useEffect } from "react";
export const LocalWeather = () => {
const APP_KEY = "XXX";
const [userPlace, setUserPlace] = useState([]);
const [localWeather, setLocalWeather] = useState([]);
async function getUserData() {
await fetch("http://ip-api.com/json")
.then((res) => res.json())
.then((data) => {
setUserPlace({
country: data.country,
city: data.city,
});
console.log(data);
})
.catch((err) => console.log(err));
}
async function getLocalWeather() {
await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${userPlace.city}&appid=${APP_KEY}`
)
.then((res) => res.json())
.then((data) => {
setLocalWeather({
temperature: Math.round(data.main.temp - 273.15),
});
})
.catch((err) => console.log(err));
}
useEffect(() => {
getUserData();
getLocalWeather();
});
return (
<div>
<h3>
Your current place is: {userPlace.country}, {userPlace.city}
</h3>
{localWeather.temperature ? (
<h4>Temperature in your city is: {localWeather.temperature} ℃</h4>
) : null}
</div>
);
};
When I try to add [] to my use useEffect eslint automatically changes it into:
useEffect(() => {
getUserData();
getLocalWeather();
}, [getLocalWeather]);
What should I do to be able to call my both functions only on the first render?
Thank you for your help!
Upvotes: 1
Views: 10273
Reputation: 281606
You can define useEffect
with an empty dependency which will ensure that the functions only run once
useEffect(() => {
getUserData();
getLocalWeather();
}, []);
However when you write it like above, eslint will complain regarding dependency. So either you can disable the warning like
useEffect(() => {
getUserData();
getLocalWeather();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
Read more about it on this post: How to fix missing dependency warning when using useEffect React Hook?
Or else if the function getUserData and getLocalWeather are mean to only be used inside the useEffect then you can declare them within useEffect
useEffect(() => {
async function getUserData() {
await fetch("http://ip-api.com/json")
.then((res) => res.json())
.then((data) => {
setUserPlace({
country: data.country,
city: data.city,
});
console.log(data);
})
.catch((err) => console.log(err));
}
async function getLocalWeather() {
await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${userPlace.city}&appid=${APP_KEY}`
)
.then((res) => res.json())
.then((data) => {
setLocalWeather({
temperature: Math.round(data.main.temp - 273.15),
});
})
.catch((err) => console.log(err));
}
getUserData();
getLocalWeather();
}, []);
However if for some reason you want to use them outside of useEffect
too and also don't want to disable the warning, you can make use of useCallback
for the functions and add them as a dependency
const getUserData = useCallback(async function() {
await fetch("http://ip-api.com/json")
.then((res) => res.json())
.then((data) => {
setUserPlace({
country: data.country,
city: data.city,
});
console.log(data);
})
.catch((err) => console.log(err));
}, []);
const getLocalWeather = useCallback(async function getLocalWeather() {
await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${userPlace.city}&appid=${APP_KEY}`
)
.then((res) => res.json())
.then((data) => {
setLocalWeather({
temperature: Math.round(data.main.temp - 273.15),
});
})
.catch((err) => console.log(err));
}, []);
useEffect(() => {
getUserData();
getLocalWeather();
}, [getUserData, getLocalWeather]);
Upvotes: 2