'setState inside useEffect doesnt update UI
i am trying to fetch multiple endpoints in UseEffect and depending on it's result show data on the UI (avatar, username, etc.)
Problem is, that the data received in the fetch()
calls inside useEffect
do in fact return the correct data but when trying to access it in the UI-Code, it will not show up.
As you can see in my code, I have the isLoading state, but I feel like the then
operation doesnt really wait until the response is there.. The loading screen will be shown for 0.5 sec but when the normal screen pops up, username, avatar, etc. are empty.
So how can I make the UI wait until useEffect
has completely loaded the data and then display it?
UserProfile.tsx
React.useEffect(() => {
AsyncStorage.getItem(LOGGED_IN_USER).then((userSteamID) =>
fetch(USER_PROFILE + userSteamID)
.then((response) => response.json())
.then((json) => json.steamId)
.then((steamId) => {
fetch(USER_INVENTORY + steamId)
.then((response) => response.json())
.then((json) => {
console.log(json);
setProfileInfo(json);
setSteamID(json.steamId);
setInventoryValue(json.value);
})
.catch((err) => alert(err))
.finally(() => setLoading(false));
})
);
}, []);
trying to use it afterwards:
if (loading) {
return (
<View
style={{
height: "100%",
justifyContent: "center",
backgroundColor: Colors.dark.background,
}}
>
<ActivityIndicator
size="large"
style={{ backgroundColor: Colors.dark.background }}
/>
<Text
style={{
color: Colors.dark.text,
marginTop: 10,
alignSelf: "center",
}}
>
retrieving userdata...
</Text>
</View>
);
} else {
return (
<Text>{inventoryValue}</Text> // avatar, etc. wont work as well
)
I Navigate from a LoginScreen.tsx
to it like so:
onPress={async () => {
let result = await startAuth();
if (result.type == "success") {
setLoggedInUser(result.steamID);
console.log("ID: " + result.steamID);
navigation.navigate("UserProfile");
}
Solution 1:[1]
Create promise chain
React.useEffect(() => {
AsyncStorage.getItem(LOGGED_IN_USER).then((userSteamID) =>
fetch(USER_PROFILE + userSteamID)
.then((response) => response.json())
.then((json) => json.steamId)
.then((steamId) => fetch(USER_INVENTORY + steamId))
.then((response) => response.json())
.then((json) => {
setProfileInfo(json);
// This can be avoided, already available in profileInfo
setSteamID(json.steamId);
setInventoryValue(json.value);
})
.catch((err) => alert(err))
.finally(() => setLoading(false))
);
}, []);
With async/await
React.useEffect(() => {
const init = async () => {
try {
const userSteamID = await AsyncStorage.getItem(LOGGED_IN_USER);
const { steamId } = await fetch(USER_PROFILE + userSteamID).then((r) =>
r.json()
);
const json = await fetch(USER_INVENTORY + steamId).then((r) => r.json());
setProfileInfo(json);
// This can be avoided, already available in profileInfo
setSteamID(json.steamId);
setInventoryValue(json.value);
} catch (error) {
alert(error);
} finally {
setLoading(false);
}
};
init();
}, []);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Rahul Sharma |