Currently, I am making a profile page where it will initially fetch the user profile details from an API endpoint. I want to have a loading indicator representing the fetch status. I am now using useState hook where I store a boolean value for isLoading state. However, after reading the documentation about useState it stated that it may be asynchronous. Hence, how do I properly update isLoading to true first then execute the fetch logic? Right now here is my code snippet.
function Profile() {
const [isLoading, setIsLoading] = useState(false);
const [user, setUser] = useState(null);
const { username } = useParams();
const fetchUserDetails = async (username) => {
setIsLoading(true);
try {
const userRes = await API.graphql({
query: queries.getUser,
variables: { username },
});
if (userRes.error) {
throw new Error({ cause: userRes.error });
}
setUser(userRes.data.getUser);
setIsLoading(false);
} catch (error) {
console.error(error);
// push to error page
setIsLoading(false);
}
};
// Fetch user profile data
useEffect(() => {
fetchUserDetails(username);
}, []);
Advertisement
Answer
In your example use case you can simply set isLoading
to true
initially and run your fetch on-mount.
function Profile() {
const [isLoading, setIsLoading] = useState(true);
const [user, setUser] = useState(null);
const { username } = useParams();
// Fetch user profile data
useEffect(() => {
const fetchUserDetails = async (username) => {
try {
const userRes = await API.graphql({
query: queries.getUser,
variables: { username },
});
if (userRes.error) {
throw new Error({ cause: userRes.error });
}
setUser(userRes.data.getUser);
setIsLoading(false);
} catch (error) {
console.error(error);
// push to error page
setIsLoading(false);
}
};
fetchUserDetails(username);
}, []);
but if you want to watch for changes to isLoading
say for a reload button, you can set it false
initially, set it to true in an on-mount useEffect and have your fetch useEffect dependent on isLoading
function Profile() {
const [isLoading, setIsLoading] = useState(false);
const [user, setUser] = useState(null);
const { username } = useParams();
// set isLoading to true on-mount
useEffect(() => {
setIsLoading(true)
},[]);
// Fetch user profile data
useEffect(() => {
const fetchUserDetails = async (username) => {
try {
const userRes = await API.graphql({
query: queries.getUser,
variables: { username },
});
if (userRes.error) {
throw new Error({ cause: userRes.error });
}
setUser(userRes.data.getUser);
setIsLoading(false);
} catch (error) {
console.error(error);
// push to error page
setIsLoading(false);
}
};
if (isLoading) {
fetchUserDetails(username);
}
}, [isLoading]);
function triggerReload() {
setIsLoading(true)
}