
No Comments Yet
Be the first to share your thoughts and start the conversation.
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, the instructor demonstrates how to fetch and display movie data in a React Native application using a custom hook. The process involves handling loading states and errors while presenting the fetched data through a Flat List component for a responsive layout.
useFetch
hook, making it easier to manage state.FlatList
component is leveraged to efficiently render a list of movies, allowing for customization through props like data
, renderItem
, and keyExtractor
.MovieCard
component is created to display each movie’s title and poster, enhancing visual appeal.00:00:02 And we are finally ready to fetch and display the movie data.
00:00:06 To do that, let's head over into our homepage, app, tabs, index.tsx.
00:00:13 Fetching the data now should be super simple, since we have already done all the hard work of actually implementing scalable,
00:00:20 reusable fetching functions that contain all of the necessary data fetching logic.
00:00:25 Let me show you what I mean.
00:00:26 Instead of handling all the states and everything right here, now we can do just a single thing.
00:00:32 Const, destructure the data that we're going to fetch, rename it to movies, and make it equal to the call of the useFetch hook coming from services useFetch.
00:00:46 To it, we have to pass a callback function, in this case, fetchMovies, which is another one of our functions we created.
00:00:55 And to it, we can pass a query, which by default will be set to an empty string.
00:01:01 Let me actually put this into multiple lines so you can better see what's happening.
00:01:05 There we go.
00:01:06 So we're calling the useFetchHook.
00:01:09 And to it, we're passing a callback function called fetchMovies to which we pass the query.
00:01:16 This query right now is empty, but later on, once we implement search or once we navigate to the search page, we can fill in the query data.
00:01:24 But it doesn't matter if it's empty right now, because you know what happens.
00:01:28 FetchMovies, if a query doesn't exist, returns the most popular movies.
00:01:33 So we're still good.
00:01:35 Now, alongside the movies themselves, back from the useFetchHook, we're also getting the loading, which I can rename to MoviesLoading.
00:01:44 And we're also getting back the error state, which I can rename to MoviesError.
00:01:50 And just so it's easier to read it, I'll put it into multiple lines.
00:01:54 And there we go, all the data we need nicely contained within a single call.
00:01:59 So let's put it to use.
00:02:01 Right below the icons logo, we can check whether we're currently loading the movies.
00:02:06 So if movies loading, in that case, we can show an activity.
00:02:12 Indicator, built right into React Native.
00:02:16 It is a self-closing component for which you can define the size.
00:02:19 In this case, I'll make it large.
00:02:22 The color, which I'll set to hash 0000FF.
00:02:27 And you can also define the class name, which I'll set to margin top of 10 and self center.
00:02:33 But if we're not loading the movies, then maybe there's an error.
00:02:38 So let's check.
00:02:39 If movies errors exist, then we will render a piece of text that'll say something like, error is equal to movies error?
00:02:51 message.
00:02:54 And finally, if we're not loading and we don't have an error, we can return a view within which we'll have the search bar and the rest of the content.
00:03:04 So basically I can just copy this view that we had before and put it right here instead of this view that I created.
00:03:11 Next, below the search bar, we can create an empty React fragment, and within it, we can display a piece of text that'll say something like,
00:03:21 latest movies.
00:03:23 To be able to see that text, let's give it a class name of text-lg, Text-White, Font-Bold, Margin Top of 5, and Margin Bottom of 3. And I'll try to reload
00:03:39 the application just to see whether the changes happen.
00:03:41 There we go.
00:03:42 You can see the latest movies right there.
00:03:44 Sometimes you have to manually restart it.
00:03:46 Now get ready to use one of the most important React Native components called a Flat List.
00:03:54 Import it from React Native, and let me show you how it works.
00:03:58 A pretty cool thing about the flat list is, is that it accepts a lot of props.
00:04:03 So for it to work, you don't have to customize it that much outside of figuring out which props to provide.
00:04:10 First of all, we have to provide the data prop.
00:04:13 That'll simply be equal to movies.
00:04:15 That's the data we're rendering.
00:04:17 And then we have to tell it how it will render each item, each one of these movies.
00:04:23 First, we can destructure that item, which is a movie itself.
00:04:27 And then for each item, we can have an immediate return.
00:04:30 What does an immediate return mean?
00:04:32 Well, it means that we're not opening up a function block here with curly braces.
00:04:37 Instead, we're opening it with parentheses.
00:04:39 So whatever we put in here, such as maybe a text element, means that we will automatically return it.
00:04:46 So for each movie, let's automatically render an item.title and give it a class name of text-white as well as text-sm.
00:04:57 So take a look at that.
00:04:59 We get back a list of 20 most popular movies at the time of the recording.
00:05:03 Pretty cool, right?
00:05:04 Another thing we have to pass into the flat list is the key extractor.
00:05:09 which simply helps React Native figure out how many elements they are and where they're positioned.
00:05:14 So same as before, we get access to the item, and we simply want to take the ID of each one of these movies.
00:05:23 Next, we can define the number of columns.
00:05:25 In this case, let's make it equal to three.
00:05:27 And then you might need to reload for the changes to take effect because you cannot change the number of columns on the fly.
00:05:34 There we go.
00:05:34 So now they're showing in three different columns.
00:05:37 Let's also define a column wrapper style by making it into an object and passing a justify content of flex-start, gap of 20 in between the elements,
00:05:52 padding of write 5, margin bottom of 10. So now if we save this, they're going to be positioned a bit more nicely.
00:06:04 And we can also pass a general class name to the entire flat list as margin top of 2 and padding bottom of 32. Also, let's say scroll enabled is set to
00:06:18 false as our entire view already scrolls by itself.
00:06:21 Perfect.
00:06:23 So now we're displaying 20 of the most popular movies in the world just by passing the movies array as data into the flat list.
00:06:32 Pretty cool, right?
00:06:34 And I think you can now get the idea of what I meant when I said that the flat list is super extensible and you can modify everything just by calling different props.
00:06:43 Data, render item, key extractor, num columns, whatever we needed to present our data nicely in a list was already there and provided to us through the
00:06:54 flat list component props.
00:06:55 And you'll find this practice pretty commonly in React Native where the pre-built components are super extensible.
00:07:03 You just have to figure out which props to pass.
00:07:05 And how can you know?
00:07:06 Well, you just Google it, which will bring you to the documentation page.
00:07:10 You can check out the example.
00:07:12 And then very quickly, you'll be able to see a list of different props that you can pass to it, and exactly what each one of these props does.
00:07:20 Pretty cool, right?
00:07:21 Let me zoom this back in right now.
00:07:23 And now that we're fetching the data properly, let's make it look a bit more interesting.
00:07:28 Of course, visuals are what's gonna change the game.
00:07:31 Right now, we are showing just the title, but what if we could show an image for each one of these movies?
00:07:38 Just so we don't have to declare it in many places, we'll create a new reusable card component for the movie.
00:07:45 So let's create a new file in the components folder and let's call it moviecard.tsx.
00:07:52 Run rnfe to quickly spin up our movie card component.
00:07:57 Give it a class name equal to text-white and text-sm.
00:08:04 And let's call it right here instead of this simple text element.
00:08:09 Instead of that, I'll call the movie card and I'll self-close it like this.
00:08:14 Now, we have a similar problem that we had before with the tabs layout.
00:08:19 where each movie card now shows exactly the same data.
00:08:23 So to be able to make it different, we have to pass the right props to it.
00:08:28 So what does it mean in this case?
00:08:30 Well, we can simply spread out all of the properties of the item or of the movie.
00:08:36 so that way we'll be able to extract them directly within the movie card.
00:08:41 So let's head over into the movie card and let's accept all of the props that we have passed into it, such as the ID, the poster underscore path,
00:08:52 the title, And where am I getting all of these from?
00:08:55 Well, remember, we already made a mock response before, and TMDB gave us back exactly the data that we're getting, such as the poster path,
00:09:05 overview, title, and more.
00:09:08 So let's get it.
00:09:10 Vote underscore average, as well as the release date.
00:09:15 And these will be of a type movie, which we declared before under interfaces.
00:09:20 So we already know what each movie has.
00:09:23 Now we want to make each one of these cards clickable.
00:09:26 Because once we click it, we want to go to the movie details page.
00:09:30 So I'll make it into a link.
00:09:33 And this link, of course, has to be imported from Expo Router.
00:09:38 It'll have an href of forward slash movie, forward slash id, and as child.
00:09:44 As child simply means that the card that is inside of the link will actually be the thing that's clickable.
00:09:50 In this case, we'll make it a touchable opacity.
00:09:54 So like a card is technically a clickable button in this case, coming from React Native.
00:10:00 We can give it a class name equal to w-30%.
00:10:03 So each card takes only 30% of the screen.
00:10:08 And within it, let's first render an image.
00:10:11 This image will have a source equal to an object where the URI is.
00:10:18 We can check if the poster path exists.
00:10:23 If it does, then we'll set it to be equal to https://image.tmdb.org/.t/.p/.w500 and then poster path like this.
00:10:44 Else, if we don't have a poster path, we can render just the placeholder.
00:10:49 So it'll be a string of https colon forward slash forward slash placeholder.co forward slash 600 by 400 forward slash 1a 1a 1a forward slash ffffff dot png.
00:11:08 Sorry for spelling out the entire URL.
00:11:10 Just thought it would be the simplest way to share it with you.
00:11:12 Now reload your application and let's also give this image a class name of w-full H-52 and the rounded dash LG for the rounded corners.
00:11:25 We can also give it a resize mode equal to cover.
00:11:29 Right below that image, still within the touchable opacity, let's also render a piece of text that will simply render the movie title.
00:11:39 And we can give it a class name of text-sm, font-bold, text-white, and margin top of 2. And there we go.
00:11:50 Once again, you can see all of these movies.
00:11:52 But hey, where is the poster?
00:11:54 Why can't we see the images?
00:11:56 Well, let's first console log the poster path to see whether we're getting back the paths of those movies.
00:12:04 So the URLs are coming back.
00:12:06 But hey, where is the poster?
00:12:08 Why can't we see the images?
00:12:11 Well, for the image to be displayed, we need to give it a URL, which I do believe we're getting as the titles are here, so the poster should be too.
00:12:19 But images also need a width and a height.
00:12:23 And I thought that I was providing a width of 100% and a height of about 208 pixels.
00:12:31 So why is it not getting applied?
00:12:33 Well, if you head over into your tailwind.config.js, you'll see that we're saying that only the app folders and files will actually include Tailwind styles.
00:12:45 But we have to do the same thing for the components.
00:12:49 So right here as the second part of the content, I can add a second string and say dot slash components, and then also target all of the components.
00:12:59 and immediately that'll allow us to apply tailwind styles within our components folder, and immediately the images will appear.
00:13:08 So this is looking absolutely amazing, and it is so nice to be able to scroll with my thumb across all of these movies.
00:13:18 And since we're using touchable opacities, you can see as I hover over them, it appears as they are clickable.
00:13:24 All of this is happening natively within our mobile application.
00:13:28 Beautiful.
00:13:28 For me, I see some of the movies that are currently popular.
00:13:32 If you're watching this video later on, for you, some different ones might be.
00:13:35 So, in the comments down below, let me know what is the popular movie from your list that you like.
00:13:41 And with that said, we also have one little error right here saying that the path of movie forward slash is not a valid path.
00:13:49 And it's actually pretty amazing that React Native can understand that we don't have a movie ID path, we only have movies,
00:13:56 plural.
00:13:57 So as soon as we change it, that's working.
00:14:00 Great.
00:14:01 So now that we're showing the image and title, already this is looking amazing, but we might as well show some more information.
00:14:09 So let me open up another view right here and give it a class name of flex-row, items-center, justify-start, and a gap of x,
00:14:22 meaning horizontal only, of 1. Within it, we can display another image, but this time, a much simpler one, just coming from icons,
00:14:33 which is coming from constants dot star.
00:14:36 So we want to display the number of stars for each one of these with a class name equal to size is set to four.
00:14:46 And below it, we can render a piece of text that'll round up the current score.
00:14:51 So I can use the math dot round, vote average.
00:14:56 divided by 2, because it goes up to 10, we want to have it up to 5. So if we do this and reload our application, the changes are still not getting applied,
00:15:06 so sometimes you might need to just reload your application by pressing Ctrl-C, and then run mpx-expost-start one more time,
00:15:14 and then press R to fully reload it.
00:15:17 But why can't we see the star yet?
00:15:19 Oh, it's not src in React Native, it's source.
00:15:23 Oh, it's those little gotchas, right?
00:15:25 That always get you.
00:15:26 There are some small differences between React and React Native, so be careful.
00:15:31 But thankfully, there aren't many.
00:15:33 Let's also give this text a class name of text-xs, extra small, text-white, and font-bold, as well as uppercase.
00:15:45 So now we can show the rating right here.
00:15:48 Below this view, let's render another view.
00:15:52 This one will have a class name equal to flex-row, items-center, and justify-between.
00:16:02 And within it, we can render a piece of text that'll have a class name equal to text-excess, text-light-300, font-medium,
00:16:14 and the margin top of 1, and within it, we can render the release date, but it'll be too long like this, so we can just split it by saying question mark
00:16:25 dot split based on the dashes, and we can only take the first part of the dash, which is the year.
00:16:33 We just care about when this movie was released.
00:16:36 And below this piece of text, we can render another that will simply say movie.
00:16:42 And we can give it a class name equal to text-excess, font-medium, text-light300, and uppercase.
00:16:53 And if you save it, it'll now say movie.
00:16:55 This is cool to have later on in case maybe some are not movies, but maybe TV shows, so you can specify which one it is.
00:17:03 But for now, I will simply comment it out.
00:17:05 And I also want to make sure that the title takes only one row, because if it doesn't, that can mess up with the view.
00:17:11 So where we have the title, that's going to be right here under this text property, we don't have to shorten the string.
00:17:18 React Native's text element comes with a pre-built number of lines prop, where you can say that this text should only take one line.
00:17:27 And immediately, you can see that it is shortened to just a single line.
00:17:32 Looking great.
00:17:33 With that in mind, I invite you to further style this card.
00:17:36 Right now, we're just showing the title, the profile photo, the rating, and the year.
00:17:41 But as you know, we're getting back so much more data about each one of these movies.
00:17:46 So, you can go ahead and utilize something else, like the original language, or the popularity, or even show the overview right here.
00:17:55 So feel free to play with it and try to further customize this card.
00:18:00 I would suggest with simply destructuring some more props from right here and then using them within your JSX.
00:18:06 But don't worry about it too much because very soon we'll be able to show all of the details about a movie within our movie details page.
00:18:15 So keeping that in mind, I am now more than happy with how our homepage is looking.
00:18:20 And if we head back to the index.tsx, You can see that we're fetching back all the movies, but now what we can do is, for the time being,
00:18:30 manually change the query to see whether our function works for fetches where we're searching for a specific movie.
00:18:39 So if I type something like Iron Man and click save, you can see that it'll reload and show all of the movies that match that search term.
00:18:49 Pretty cool, right?
00:18:50 And if I bring it back, we're back to where we were.
00:18:53 It's not that hard, right?
00:18:55 Once you understand the basics, using it the next time will feel much easier.
00:18:59 But this was just one example of creating a custom hook for fetching data.
00:19:04 You can create custom hooks for many other things, like handling forms, like React hook form, managing themes, or storing data in local storage.
00:19:13 You can do whatever you want, but don't get me wrong.
00:19:15 you don't always need to create your own hooks.
00:19:18 Only when it really makes sense to do so.
00:19:20 Because React 19 comes with a lot of pre-built hook.
00:19:24 Like the use hook.
00:19:26 Yep, it's only used like this.
00:19:29 And it does some pretty cool things.
00:19:31 There's also the use action state, use form state, use transition, which make working with forms and requests much easier.
00:19:39 And I actually explain all of these in detail with real examples and even better projects within the new React Native course that I'm right now building
00:19:50 for JS Mastery Pro.
00:19:52 It's a new learning platform where you can learn lesson by lesson with real examples and even better projects.
00:19:59 So go ahead and check it out.
00:20:01 I'll leave the link in the description.
00:20:03 But with that, let's go ahead and develop the search.
00:20:05 So we no longer have to manually pass the query right here.
00:20:09 Instead, we can use the actual search page and then pass over real values.
00:20:15 Great job so far.
00:20:16 The app is already looking amazing, but now we'll make it stand out with even better functionalities.