I have a list of posts that I am mapping through and want to get the associated author data and avatar photo url, for each post. I have functions that make api calls and return this information, when called on each post. Then the username, full_name & avatar_url are added to the post, so that when rendering the data in the component, all of the data is available.
See the custom hook:
// Custom hook to fetch the user & avatar for each post and combine them
function usePostsWithUserDetails(posts) {
const [combinedPosts, setCombinedPosts] = useState([]);
useEffect(() => {
// Make async call for session & avatar_url that match the post
const fetchData = async () => {
const combineData = posts.map(async (post) => {
const [user, avatar] = await Promise.all([
getSessionProfile(post.user_id),
fetchProfileAvatar(post.user_id),
]);
// Add the needed data to the post
post.username = user.username;
post.full_name = user.full_name;
post.avatar_url = avatar;
});
setCombinedPosts(combineData);
};
fetchData();
}, [])
return combinedPosts;
}
So my problem is that when I go to add the data to the post (ie: post.username = user.username), that data may not have been returned from the async function. I am fairly new to React and still haven’t gotten the hang of how to return the promise when it’s needed.
I believe you would normally want to add the data, after it’s returned from the useEffect. This issue being that this needs to happen for each post. The only other solution I can think of is to have the needed data added to the table when the post is created but at some point I am going to need to query other tables and combine data.
Any direction is much appreciated. 🙂
2
Answers
Update One: (using some hints from Dominic to try and fit it all in one function)
Functions from apiService to fetch the profile and avatar from Supabase:
Fetch Avatar:
You need to wrap your map in a
Promise.all
. Also you shouldreturn
the modified post in the map loop.