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) }