I have an app that allows users to create posts. With Firebase I had the posts nested in the user documents as JSON instead of having a separate posts collection. For Supabase, everything I have seen says to have a table called profiles
and a separate table for posts
but this makes getting the data a more difficult process. In every row of the posts
table, I have a uid
column. This allows me to also fetch the user from profiles
for each post. I am yet to find a good way of fetching this data. I have tried multiple different ways to do this, the best being two different functions; one to fetch posts and then one to fetch the user for each post. However, this solution has not been reliable and sometimes returns undefined
. I want the arrays of users and posts to be shared through all screens. On top of that, I would like to use pagination to only fetch 10 posts at a time. I did have this working to an extent in Flutter but now that I am moving to React Native I would like to find a solid solution. Below is my current solution that is returning undefined
sometimes. I appreciate any help with this.
DataService.tsx
:
export async function posts() { // const { from, to } = getPagination(page, 10); const { data, error } = await supabase .from("posts") .select() .order("date", { ascending: false }); var postsList: Array<Post> = data!.map((post) => new Post(post)); console.log(postsList); // Logs as expected return postsList;}export async function users() { var postArray = await posts(); var completed = 0; var userArray: Array<User> = []; for (var post of postArray) { const { data, error } = await supabase .from("profiles") .select() .eq("uid", post.uid) .single(); const user = new User(data); completed = completed++; if (!userArray.some((u) => u.uid === user.uid)) { userArray.push(user); } userArray[userArray.indexOf(user)].posts.push(post); console.log(userArray); // Logs as expected } if (completed === postArray.length) { return userArray; }}
Example of using the data:
const [postsArray, setPosts] = useState<Array<Post>>(); const [usersArray, setUsers] = useState<Array<User>>(); useEffect(() => { (async () => { const newPostsArray = await posts(); setPosts(newPostsArray); console.log("Posts: " + postsArray); // Usually logs as "Posts: undefined" const newUsersArray = await users(); setUsers(newUsersArray); console.log("Users: " + usersArray); // Usually logs as "Users: undefined" })(); }, [setPosts, setUsers]);
User
:
User { uid: string; blockedUsers: Array<string>; posts: Array<Post>; photoURL: string; displayName: string; verified: boolean; constructor(user: any) { this.uid = user.uid; this.blockedUsers = user.blockedUsers; this.posts = user.posts; this.photoURL = user.photoURL; this.displayName = user.displayName; this.verified = user.verified; }}
Post
:
export default class Post { imageUrls: Array<string>; postId: string; uid: string; caption: string; location: Location; date: number; constructor(post: any) { this.imageUrls = post.imageUrls; this.postId = post.postId; this.uid = post.uid; this.caption = post.caption; this.location = post.location; this.date = post.date; }}