Extract Tweet RenderItem0:00
Let's make a small refactor so we can share some presentation logic between the home screen and the list of tweets, and the profile screen and the list of tweets here. So if you remember, we have a flat list for the list of tweets on the home screen, it's right here. And we have this renderItem method, which renders one of the tweets here. So this looks pretty much the same thing as what we need in here, just the data is different. So on the home screen, let's check out this renderItem method. It's within the same file. So what we want to do is extract this to its own file, and then make use of it on the profile.
It's within the same file. So what we want to do is extract this to its own file, and then make use of it on the profile screen as well. So let's go ahead and do that. So let me just bring this back, let's make a new folder here called components. So components, and let's name this renderItem.jsx. And it's going to be a functional component. So let's get rid of this. Actually, let's get rid of the brackets as well, we'll just copy it from our homeScreen here.
Actually, let's get rid of the brackets as well, we'll just copy it from our home screen here. Let's grab the params first. Paste that in here, okay. And like I said, we will grab everything here and paste it into our file. So everything here, okay, let's paste this in. And I'm going to grab all the imports on this file as well, sorry, on this file. And just paste it in, and we'll remove what we don't need. We can make use of VS Code for that as the ones that are not being used are grayed out. So let me just paste that in.
We can make use of VSCode for that as the ones that are not being used are grayed out. So let me just paste that in. And you can see everything that we're not using. So we actually don't need any of this because this is going to remain on the parent component for fetching the data. We do need a stylesheet, you don't need a FlatList. Again, that's going to be on the parent. And so is the ActivityIndicator. So we'll remove that. Looks like this is not being used, the Axios call will be on the parent component.
So we'll remove that. Looks like this is not being used, the Axios call will be on the parent component. And that's good for now. Let's save that. We also need to grab the styles. So let's go to our home screen. Let's grab the style sheet here. Or everything in the style sheet. Let's grab this. And let's put it in our renderItem down here.
Let's leave this for now. But now let's try to make use of the external file instead of the one we have here. So we can, for now, I'm just going to comment this out. So it's all of this. And let's import this new file that we created. So let's put it down here. Import renderItem right here. Okay. So let's save that. We should get an error.
So let's save that. We should get an error. Because we commented out that renderItem in our FlatList right here. But now let's try to make use of that external file. renderItem. Okay. Okay, so it looks like it does work. But now the presentation logic for rendering one of the tweets is in an external file. So we can make use of it in our ProfilePage as well. So let me just remove this.
So we can make use of it in our profile page as well. So let me just remove this. And we can also clean up some of these styles that we don't need in our home screen. So for example, am I using ml-4 here? No. I'm only using it in the renderItem. So we can get rid of this. And most of this I'm not using as well. For example, text-gray. Yeah, all of this is within the renderItem.
And we'll paste that back in. Uncomment. And save. And the separator is back. So for our renderItem, we can keep everything or mostly everything except the separator. Where is it? separator. Okay. Let's get rid of this. Save that.
Let's get rid of this. Save that. It's the same. And we can also get rid of this container here, since this is on the parent component. Okay, cool. So now let's see if we can make use of this in our profile screen. So let's go to our profile screen. And we can't find variable. Go to profile. Oh, yeah.
Fix Navigation in Component5:24
Go to profile. Oh, yeah. So we need to move that logic over as well. So let's do that. So go to profile. So all of this. Actually, this can stay here because the button lives on this component. But these two now have to go within the RenderItem component. So let's cut this out. Let's go to our RenderItem.
So let's cut this out. Let's go to our renderItem. And let's paste those methods in here. Let's put it right here. Okay. But now we don't have access to this navigation prop, and we can't pull it from here because we can only pull it from here if it is a screen. So if you look at the React Navigation box, we can make use of this useNavigation hook to still have access to this navigation variable. So let's do that.
to still have access to this navigation variable. So let's do that. So let's copy this. Let's put it in here. Let's make sure to import use navigation. Okay. And let's save that. Okay. Let me just reload the app here. Okay.
Create User Tweets Endpoint7:44
So back to our backend. We can also combine it if we wanted to with our User profile. And that's definitely an option if you only want to make one request. But the way I did it was I made a separate endpoint. So that means we need to make two requests on this screen. So one to get the User's information, and then one to get the User's tweets. But sometimes you might feel like you're making too many requests. And in that case, you can combine them or make use of a more modern approach and use GraphQL instead of REST APIs. So let's go ahead and make that endpoint.
GraphQL instead of REST APIs. So let's go ahead and make that endpoint. So let me just grab this one here. Actually this one here. Let's paste that in. So it's going to be users. We're going to grab the user and we want their tweets. This is going to be a user. And we can say userTweets because we have that relationship. So let's save that.
And we can say User tweets because we have that relationship. So let's save that. Let's check out our REST client. Let's try that out here. So user, user, users, user, and then tweets to grab their tweets. And right now this user only has one tweet. So this is correct. However, we also want to maintain the infinite scroll. So we need to paginate our tweets here. So let's say paginate.
So we need to paginate our tweets here. So let's say paginate. This might not work because this is on the collection. Let me just see, say 10. Yeah. So that doesn't work. We might have to make this a method. Okay. So that works. Okay.
Fetch Tweets on Profile9:32
So that works. Okay. Now let's go ahead and grab this information from our front end. So let's go ahead and go to our profile screen. So we already have the useEffect hook. So let's make a new method here to grab the user's tweets. So getUserTweets. Okay. And like I said, we want to maintain the infinite scroll and the pull to refresh. So let's grab the method here that has all of that information.
And like I said, we want to maintain the infinite scroll and the pull to refresh. So let's grab the getAllTweets method here that has all of that information. So that's going to be, what's it called? Not this one, but the other one. So let's copy this. Let's paste this in here underneath this one. Okay. Let's just remove this. Actually we'll leave that.
Let's just remove this. Actually we'll leave that. We might use that. Let's change the endpoint here or let's change the name first. So get user tweets. The endpoint is users/{user}. So we have route.params.userId and we have /tweets. And we still need all of this logic here. So the page, the state for checking if we're at the end of scrolling and so on. So we also need another loading state because the one I already have is for loading the
So the page, the state for checking if we're at the end of scrolling and so on. So we also need another loading state because the one I already have is for loading the profile information. So let's make a new one called setIsLoadingTweets. Same for this one. Okay. So let's go back to the HomeScreen and grab all of that state that we need. So there's some duplication in this case where we're duplicating the logic for grabbing the information from the server as well as the infinite scroll and the pull to refresh. I'm okay with this because there is some differences.
So you can abstract some of this logic within that custom hook. But like I said, for now I'm okay with duplicating it. So let's grab all of this state here. So all of this, let's go back to our profile screen and let's add that. Let me just get rid of the sidebar here. So data is our tweets. Maybe I should have named it tweets instead of data, but I'll just leave it to keep it consistent. So we already have isLoading. So this isLoading should be for our tweets.
So we already have is loading. So this is loading should be for our tweets. Is refreshing is for pull to refresh. We need the page for infinite scroll, and this is to check if we're at the end of scrolling. Okay. So for the FlatList down here, where is it? FlatList. Let me just comment it out for now. I just want to make sure that we're getting the data from the server so we can get rid of this as well.
I just want to make sure that we're getting the data from the server so we can get rid of this as well. Get rid of this. Okay. And let me just console.log the data coming back from the server to make sure that is correct. Okay. There's nothing being rendered here. So let's just say view. Okay.
So let's just say view. Okay. Let's check our console and it looks like we are getting the list of tweets here. Okay. Let's put our flatList back. And for our data, it should be data now, which is coming back from our server and renderItem should be from the external file that we created earlier. So let's grab the import right here, and then we'll grab the renderItem. So let's grab this, import this. Okay.
Handle Missing Tweet User14:22
Let's put it here. Let's close that out and let's put it here. Okay. Save that. So now we're getting this error says undefined is not an object. So it says tweet.user.avatar. So if you take a look at our REST client, and if you refresh this, you'll see that there's no user information within our tweets here. And if you take a look at our renderItem, we are referencing that tweet.user a few times. So for our userId, our avatar and so on, name and username.
And if you take a look at our renderItem, we are referencing that tweet.user a few times. So for our userId, our avatar and so on, name and username. So what we can do is check which screen we're on and then reference the user depending on which screen. So if we're on the home screen, we can stick to this. But if we're on the profile screen, we can just say something like the user.name because we already have the user. Or the easier way, since we have control over our backend, is to add that information for our tweets. So again, it's a bit redundant because we already know that the user for each tweet.
our tweets. So again, it's a bit redundant because we already know that the User for each tweet will be the same because we're on the profile screen, but it makes our front end code much cleaner. So let's go back to our backend. With each Tweet, we can just load the User as well. So we can say with('user'), and then that will work. And let's also make sure to just grab the information that we want. So for example, this here. Okay, let's replace this.
So this is the one tweet for this User. So what is this error here? I believe this has to do with the ID. So let's go back to our front end. Let's go to the flatList. Sorry, flatList for our profile screen. flatList. Yeah. So the key should be a string. And we have the same thing for our home screen.
So the key should be a string. And we have the same thing for our home screen. We just call toString on our ID here. Okay. .toString. Okay. I guess I don't need this styles.container anymore because we have it on this view here. Let's see what happens if I get rid of it. Okay. It's the same.
So that's fine. Let's just add one more Tweet here to make sure it looks okay. So or maybe we'll add two. Tweet one. Okay. So this User has one so far, unless they have more down here. Let me just add another one. Tweet two. Okay. So now if I go into this person's profile, you'll see all their tweets.
Add Refresh and Pagination18:25
And it's all of this stuff here. So refreshing on refresh and all of this other stuff. So let's grab this. Let's paste it into our ProfileScreen. And we're also going to need the handleRefresh and handleEnd. So like I said, we do have some duplication here. And if you want to get rid of that, you can make use of custom hooks. handleEnd. Let's grab this. Also handleRefresh.
Let me reload the app and see if those things still work. So pull to refresh. Okay. Can't find variable. getAllTweets. Oh, I forgot to change that. getAllTweets. Or handle refresh. It should be getUserTweets. Okay.
It should be get user tweets. Okay. Let's reload. Try that again. Pull to refresh. And what is this line here? So unfortunately, I don't know what that line is. I think it has to do with the scroll bar of the FlatList. But I also want to make sure that the infinite scroll still works. So I have to add a bunch of tweets here.
If I save this, does that fix it? And it looks like it does. Cool. So our profile screen is now complete. We are pulling this user's tweets from the backend. And we're also sharing some logic between this and the tweets on the homepage. So let's go ahead and make a commit as always. Say git add, git commit, add tweets on profile page. And then for our backend, git add, git commit, add endpoint for pulling user tweets.
And then for our backend, git add, git commit, add endpoint for pulling user tweets.
