
No Comments Yet
Be the first to share your thoughts and start the conversation.
If you're having trouble with the expo initial configuration with Expo v51, run this command:
npx create-expo-app@latest ./ --template blank
Be the first to share your thoughts and start the conversation.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
In this lesson, we focus on developing a user profile page that fetches user-specific data, such as the avatar, username, number of posts, and videos created by the user. The session guides you through modifying and integrating components to enhance the profile view, as well as implementing logout functionality.
getUserPosts
to fetch posts created by the logged-in user.useGlobalContext
to access the current user's ID without additional queries.InfoBox
component to showcase user statistics like posts and followers.00:00:00Â The next screen we can focus on will be profile.
00:00:03Â So let's click on profile right at the bottom right corner.
00:00:07Â And we have an empty screen.
00:00:08Â Let's turn it into something that looks more like this, where we fetch the avatar, username, the number of posts and some fake views,
00:00:16Â and also display all of the videos that that user has created.
00:00:20Â To do that, we can copy the entire code from our query file, close all of the currently open files, and navigate over to profile.
00:00:30Â There, we can override the entire code with what we copied from the query and rename it to profile right here and also right here at the top.
00:00:45Â That should immediately give us something better to look at.
00:00:48Â There we go.
00:00:49Â It says no videos found.
00:00:50Â It says search results.
00:00:52Â But let's first make it into an actual profile by modifying which posts are we trying to get.
00:00:57Â We're not trying to get the posts that we search for.
00:01:00Â Rather, we're trying to get the posts that our user has created.
00:01:05Â So let's navigate over to AppRight, duplicate the search posts right below, and let's call it something like getUserPosts where we can pass the user ID
00:01:17Â so we know which user posts are we getting.
00:01:19Â We also list the documents coming from database ID with this collection and query.equal where the creator is equal to user ID.
00:01:31Â That's it.
00:01:32Â You can see how simple it becomes once you understand how all of this works.
00:01:36Â Now, we can go back to profile.
00:01:38Â And instead of fetching these posts and refetch from search posts, we can simply call getUserPosts coming from libAppWrite like this.
00:01:49Â And to it, we're going to pass the user ID.
00:01:53Â But the question is, where do we get the currently logged in user ID?
00:01:58Â Pause this video, give yourself a moment and try to figure it out.
00:02:02Â I'm going to let you know in three, two, one.
00:02:07Â It's coming from the global context.
00:02:10Â It is right here.
00:02:12Â Remember under values, we're passing the user as the object.
00:02:16Â We can get access to it and the user contains the ID.
00:02:20Â So we don't need the query in this case.
00:02:23Â Rather, we can say const destructure the user, the set user, and the set is logged in because from here we'll also be able to log out.
00:02:34Â And we can say that's equal to use global context.
00:02:39Â which is coming from our context.
00:02:41Â It doesn't want to auto import it, but we can say import use global context from dot slash or no, it's dot dot slash dot dot slash context forward slash
00:02:54Â global provider.
00:02:55Â And then we get the user.$id.
00:02:58Â And this should give us access to all of the posts.
00:03:02Â Looks like it redirected us back to home, so we can click to go to the profile again.
00:03:07Â And it's going to complain about the query.
00:03:09Â We no longer need this use effect with the query.
00:03:13Â Let's save it now and go back to profile.
00:03:16Â It's going to complain again because we're using a query in a couple of places.
00:03:20Â So let's simply comment out the query here and here.
00:03:24Â And I think that's it.
00:03:26Â If we save it and click profile once again, we can see our three videos that we have created, which is exactly what we wanted.
00:03:35Â So now the last thing we have to do is change the header of this flat list displaying our posts into something that looks like this.
00:03:43Â We basically want to add this user card at the top that lets us know that we can log out and that we're currently on the profile page.
00:03:51Â We can do that by modifying the list header component part of our flat list.
00:03:56Â In this case, let's delete everything we have in there right now to make it a bit easier for us to develop it.
00:04:03Â And we can first wrap everything in a view.
00:04:06Â That view will have a class name equal to w-full, justify-center, items-center, margin top of 6, margin bottom of 12, and padding X of 4. Within that div,
00:04:22Â we can show a touchable opacity that looks something like this, and we import it from React Native.
00:04:29Â Within it, we can show an image with a capital I.
00:04:33Â also coming from React Native with a source equal to icons.
00:04:41Â and don't forget to import icons from constants.logout with a resize mode equal to contain and a class name equal to w6h6.
00:04:55Â You can see this logout on top.
00:04:58Â Let's also put it at the end by styling detachable opacity by giving it A class name equal to W full, items end, and margin bottom of 10. That way it's
00:05:14Â at the top, right?
00:05:16Â Also later on to this touchable opacity, we'll have to provide a function that implements the logout functionality.
00:05:23Â So let's simply declare it right here, const logout is equal to a function that looks like this.
00:05:31Â And we call it on press.
00:05:34Â Great.
00:05:34Â Now below this touchable opacity, we want to show a view where we render the user's avatar.
00:05:41Â So let's do just that.
00:05:43Â view with a class name of W16, H16, border, border secondary, that looks something like this, rounded-lg, justify center,
00:06:01Â and items center.
00:06:04Â And within it, we can show a new image property that has the source equal to an object of URI is equal to user?avatar.
00:06:17Â That's going to look something like this.
00:06:19Â It's not visible until we give it a class name equal to w-90%.
00:06:25Â H dash 90% as well within square brackets.
00:06:30Â That way it's not going to take the full width of the screen.
00:06:33Â And the rounded dash LG.
00:06:35Â And the resize mode equal to cover.
00:06:39Â Okay, this is great.
00:06:41Â And right below that image and below this view, we can render a new custom component called InfoBox.
00:06:49Â So let's create it.
00:06:50Â New file, InfoBox.jsx where we can run rnfe.
00:06:58Â And we can immediately import it right here.
00:07:01Â InfoBox.
00:07:03Â Make sure to properly import it at the top.
00:07:06Â InfoBox coming from InfoBox.
00:07:11Â We don't need the use effect, the search for rams, nor the text right here.
00:07:15Â That's good.
00:07:16Â If we save it, there's going to be nothing there, but to this info box, we can pass a couple of props like title is equal to user question mark dot username.
00:07:27Â container styles equal to margin top of five.
00:07:31Â So we divide it a bit from the top and title styles equal to text-lg as this will be a bit larger, title styles.
00:07:41Â Below that info box, we'll create a view that will have a class name equal to margin top of five.
00:07:49Â and flex row and here we want to show two more info boxes so let's simply copy this one paste it once and also paste it twice the second one will render
00:08:03Â the number of posts that we have so posts.length or zero if we don't have any We're going to also give it a subtitle of posts,
00:08:16Â container styles of margin right of 10, title styles of text dash XL.
00:08:24Â And finally, the last info box will show a number of followers.
00:08:29Â We can say something like 1.2 thousand with a subtitle equal to followers.
00:08:37Â We don't need the container styles and it will have a title of text-xl.
00:08:43Â If we save it, you basically can't see anything on the screen right now.
00:08:47Â That's because we're not making use of any of these parameters we're passing.
00:08:52Â But now we have the structure, so we know which props are we accepting.
00:08:57Â So going to our info box, we can now accept a couple of props, such as title, subtitle, container styles, and title styles.
00:09:09Â We can render a view.
00:09:11Â with a class name of container styles with a text that will render the title.
00:09:17Â Let's give it a class name equal to, let's make it dynamic, text-white, text-center, font-p, semi-bold.
00:09:30Â And we can also render all the title styles we're passing like this.
00:09:36Â There we go.
00:09:36Â We can see JS Mastery, three posts and 1.2 thousand followers.
00:09:41Â And we can create a new text element right below it for the subtitle that will have a class name equal to text-sm for small,
00:09:52Â text-grey-100, text-center and font-p regular.
00:10:01Â And let's save it.
00:10:02Â There we go.
00:10:03Â So now we can see one primary info box that renders our username, we can see our subtitle of posts and title of three, and same thing for the followers.
00:10:13Â And with that, my friends, believe it or not, our profile page has been completed.
00:10:19Â It's pretty crazy what you can achieve when you reuse existing components.
00:10:24Â We have reused almost everything, our page, our routing structure, our flat list from home and search, and also the individual video cards,
00:10:34Â which, don't forget, you can also play.
00:10:37Â And make sure to mute it every time, especially if you're using these videos, as they're quite loud.
00:10:42Â So this is phenomenal.
00:10:44Â So finally, let's implement our logout function so we can log out of the application and maybe log in with another account.
00:10:52Â We can do that by creating another AppWrite function.
00:10:56Â We can say export const sign out equal to an async function with a try and catch block.
00:11:07Â In the catch, we throw a new error with the error message.
00:11:12Â And in the try, we can say const session is equal to await account.delete session.
00:11:22Â And we pass in current.
00:11:24Â We want to delete the current session and return the session that we just ended.
00:11:29Â With that in mind, we can go back to profile.
00:11:33Â We can say await and call the sign out function being imported from AppRite.
00:11:39Â Since we're using await, we have to make this function async.
00:11:44Â We also want to set our global state user to be equal to null.
00:11:48Â And you want to set isLockedIn to be null or rather false in this case.
00:11:54Â And you want to re-navigate to sign in by importing the router coming from Expo router.
00:12:04Â And then right here, we can say something like router.replace pointing to forward slash sign in.
00:12:13Â If we do that, go back to the profile and click the logout icon on top, right?
00:12:20Â We have been logged out and if you try to go back, you can't because we have replaced the URL, not pushed it.
00:12:27Â So this is the difference between push and replace.
00:12:29Â Now let's see if I remember my username.
00:12:32Â I think I used contact at JS Mastery Pro.
00:12:36Â And I believe it was one, two, three, one, two, three, one, two, three.
00:12:43Â And I'm going to click sign in.
00:12:46Â And I was right.
00:12:48Â We are back in, we can see all the videos loading.
00:12:52Â It says, welcome back JS Mastery.
00:12:54Â And I think that JS Mastery part is hard coded right now.
00:12:58Â So let's quickly copy this use global context from profile and navigate over to home.
00:13:05Â Let's use that same hook and import use global context from dot dot slash dot dot slash.
00:13:16Â Context and then global provider.
00:13:20Â We get this user.
00:13:21Â And then here where we hard coded JS Mastery, we can say something like welcome back comma.
00:13:29Â And then here we can render user question mark dot username.
00:13:34Â Oh, it looks like it's not there.
00:13:36Â Let's check out our collection.
00:13:39Â It is username.
00:13:40Â Yes, JS Mastery is the username.
00:13:43Â We can see that right here.
00:13:45Â So let's say user.username.
00:13:48Â I think that's exactly how we have used that in the profile as well, right?
00:13:51Â We get the user from the global context, and then we're using it by saying user?username.
00:13:58Â In this case, it doesn't seem to appear though.
00:14:01Â So let's try to console log it right here on top, console.log, user.username.
00:14:10Â I'm going to open up this and it does say undefined.
00:14:15Â What if it console log just the user?
00:14:18Â we get null for user.
00:14:20Â And what would I get if I console log the user on the profile page?
00:14:25Â Let's see if I can do that right here.
00:14:28Â Console log user and navigate to profile.
00:14:32Â It's also null and actually my app breaks.
00:14:35Â You can see it here where I share my phone screen.
00:14:38Â It completely crashed saying cannot read property ID of null.
00:14:43Â So I simply reloaded the entire application and logged out completely.
00:14:47Â It looks like the second time that we logged into our account, for some reason, it didn't set user to the global context.
00:14:57Â Let's see why that is.
00:14:59Â Here we have the set user.
00:15:02Â And we're setting it once we get the current user.
00:15:05Â That looks good.
00:15:06Â But then if we move over to sign in, oh, would you look at that?
00:15:11Â I even left myself a comment, set it to global state, but I never got around to doing it.
00:15:17Â And we also didn't do it on sign up.
00:15:19Â So I'm a bit confused how it even let me in and kept me logged in this entire time, but for some reason it did.
00:15:26Â So let's fix this.
00:15:28Â The only thing we have to do right here Let's do the sign in first.
00:15:33Â Is, get the information about the current user by saying const result is equal to await.
00:15:40Â getCurrentUser coming from libAppWrite.
00:15:44Â And then we can set that user to the state by accessing our global state const setUser and setIsLoggedIn is equal to useGlobalContext coming from the global
00:16:00Â context provider like this.
00:16:02Â And this is supposed to be setNotSir.
00:16:05Â And now we can simply call setUser to be equal to result.
00:16:10Â And we can set is logged in to be equal to true.
00:16:16Â And then we point to home.
00:16:18Â So this is now good.
00:16:19Â And we can also copy these three lines and go to sign up.
00:16:24Â We can paste it right here, but in this case, we don't even have to get the current user because we're creating it for the first time.
00:16:30Â So we already have it.
00:16:32Â The only thing we do have to get is set user and set is logged in, in the same way that we have gotten it here.
00:16:39Â Import, use global context, and then use the hook that we created right here.
00:16:46Â That looks good to me.
00:16:49Â I'm going to save it.
00:16:50Â And now we should be properly logging in and saving that information to the global context.
00:16:56Â Let's give it a shot.
00:16:58Â I'm going to go continue with email.
00:17:01Â I will use my contact at JS Mastery.
00:17:05Â And I think my password is 123-123-123.
00:17:07Â Let's go ahead and sign in.
00:17:13Â We are right in, and as you can see on the top, it says, welcome back JS Mastery.
00:17:18Â So now it actually knows your username.
00:17:22Â And if you go to profile, that looks great as well.
00:17:26Â I use very high res thumbnails, so it takes some time to load, but for smaller ones, it should be quicker.
00:17:32Â So this is great.
00:17:35Â With that in mind, the onboarding, the sign in and the sign up page are looking as good as ever and they're fully functioning right now.
00:17:42Â The home screen is just stunning where we can play different kinds of videos.
00:17:48Â Make sure to mute them first.
00:17:49Â We can also make the videos full screen, which is pretty amazing if you ask me.
00:17:55Â You can also rotate your device.
00:17:58Â We have also implemented search so we can search for, as we said, journey and press search.
00:18:04Â That works as well.
00:18:07Â And finally, we have also implemented the profile where you can see what the currently logged in user has created and we can also log out on top right.
00:18:16Â And finally, we'll implement a screen within which you'll be able to upload your own videos and thumbnails and therefore create new documents and add them
00:18:27Â to our database and then show them within our homepage.