Reputation: 348
I have a couple problems with a fetch I'm making to my api in my react profile view. I'm not able to view the data in a p element of the render but I am able to view the user object my profile function spits out in the render... also the function loops forever, never displaying the data in the p element like I want but making unlimited fetchs and spitting out the correct object to the console. I feel like I'm doing a few things wrong here. Help please.
import React, { useState } from "react";
import Loading from "../components/Loading";
import { useAuth0 } from "../react-auth0-spa";
const Profile = () => {
const { loading, user } = useAuth0();
function subSplitter(subscriber){
return subscriber.sub.split("|")[1];
}
var sub = subSplitter(user);
console.log(sub);
const [showResult, setShowResult] = useState(false);
const [apiMessage, setApiMessage] = useState("");
const { getTokenSilently } = useAuth0();
const responseData = [];
const getGames = async () => {
try {
const token = await getTokenSilently();
const response = await fetch("http://localhost:5000/api/users/" + sub, {
headers: {
Authorization: `Bearer ${token}`
}
});
const responseData = await response.json();
setShowResult(true);
setApiMessage(responseData);
console.log(responseData.games);
return responseData.games;
} catch (error) {
console.error(error);
}
};
var stringUser = JSON.stringify(user, null, 2);
var gottenGames = JSON.stringify(responseData.Games, null, 2);
getGames();
if (loading || !user) {
return <Loading />;
};
return (
<div>
<img
src={user.picture}
alt="Profile"
className="rounded-circle img-fluid profile-picture mb-3 mb-md-0"
/>
<h2>{user.name}</h2>
<p className="lead text-muted">{user.email}</p>
<p>{stringUser}</p>
<p>{gottenGames}</p>
</div>
);
};
export default Profile;
Upvotes: 1
Views: 2494
Reputation: 202
I think you are aware of the async behavior of javascript. So I am noting down some bugs in your code:
var gottenGames = JSON.stringify(responseData.Games, null, 2);
is executing before you call API to assign data to it thus it got undefined
; const responseData = [];
you declare const to responseData in component and also in getGames function
so returned data is only assign to local const variable inside the function and outer const
variable did not change.One of the Solution: `
gottenGames = getGames();` you directly assign returned data to gottenGames and initially declare it empty.
Upvotes: 1
Reputation: 679
Actually this is not the correct way to fetch data in React. The code snippet below shows how to do data fetching in React. There is something called the [useEffect] hooks that allows you to do side-effecting actions in a component.
import React, { useState, useEffect } from "react";
import Loading from "../components/Loading";
import { useAuth0 } from "../react-auth0-spa";
const Profile = () => {
const { loading, user } = useAuth0();
function subSplitter(subscriber) {
return subscriber.sub.split("|")[1];
}
var sub = subSplitter(user);
console.log(sub);
const [showResult, setShowResult] = useState(false);
const [apiMessage, setApiMessage] = useState("");
const { getTokenSilently } = useAuth0();
const responseData = [];
useEffect(() => {
const getGames = async () => {
try {
const token = await getTokenSilently();
const response = await fetch("http://localhost:5000/api/users/" + sub, {
headers: {
Authorization: `Bearer ${token}`
}
});
const responseData = await response.json();
setShowResult(true);
setApiMessage(responseData);
console.log(responseData.games);
return responseData.games;
} catch (error) {
console.error(error);
}
};
getGames();
}, []);
var stringUser = JSON.stringify(user, null, 2);
var gottenGames = JSON.stringify(responseData.Games, null, 2);
if (loading || !user) {
return <Loading />;
}
return (
<div>
<img
src={user.picture}
alt="Profile"
className="rounded-circle img-fluid profile-picture mb-3 mb-md-0"
/>
<h2>{user.name}</h2>
<p className="lead text-muted">{user.email}</p>
<p>{stringUser}</p>
<p>{gottenGames}</p>
</div>
);
};
export default Profile;
All I changed to your code was wrap your data fetching call inside an useEffect hook.
One more thing to note here is that doing this const responseData = [];
is probably a bad idea. Mutations in React should only be handled using useState
or the component state for class-based components. So your reponseData
should actually look like this snippet below.
// declaring state variable
const [responseData, setResponseData] = useState([]);
// inside your data fetching function
const data = await response.json();
setResponseData(() => data.games)
Let me know if this clears things up or not!
Upvotes: 2
Reputation: 1625
You are never assigning the return value of getGames()
to anything.
Try changing this ..
var gottenGames = JSON.stringify(responseData.Games, null, 2);
getGames();
To this ...
var gottenGames = JSON.stringify(getGames(), null, 2);
Upvotes: 0