
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.
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
00:00:00Â To get started with our search, we can navigate over to App, Search, and then Query right here.
00:00:09Â Can you see how this file is within square brackets?
00:00:12Â Well, that means that we can extract the value of that search out of the, well, not URL, but out of the screen.
00:00:19Â So how do we do that?
00:00:21Â Well, in React Native, you can say const, Query is equal to use local search params and this use local search params is coming from expo router.
00:00:35Â So let's import it, use local search params from expo router.
00:00:41Â What we can do right now is simply make this text a bit larger by giving it a text three Excel as well as text dash white.
00:00:51Â And within it, we can now render this dynamic query.
00:00:55Â So let's see if that works.
00:00:57Â What we want to do is navigate to this dynamic page.
00:01:01Â And if I'm not mistaken, we haven't yet implemented the logic within our search input component.
00:01:09Â It looks good, but we still have to make it do something on click.
00:01:13Â So right here, instead of using this password, we no longer need that.
00:01:19Â we can get access to the path name by saying cause path name is equal to use path name like this and we call it as a hook this use path name can be imported
00:01:33Â from expo router so import use path name coming from expo router There we go.
00:01:41Â That's good.
00:01:43Â And we also can create a new use state field and we can call it query set query at the start equal to let's do just an empty string.
00:01:55Â We don't have to pass any props into the search input.
00:01:58Â So let's delete it.
00:01:59Â And then here where we use the value, we can rather refer to the query.
00:02:05Â We don't have to make it a secure text entry.
00:02:08Â And on change text, we simply want to get the event and set the query and pass that event.
00:02:16Â We can also change the placeholder text color to hash, cd cd e0, which is going to make it pop just a bit.
00:02:25Â Then in the touchable opacity, we can add an on press.
00:02:29Â This is as if we're adding a click handler on the button.
00:02:33Â onPress is equal to a callback function where we check if query exists, or rather if query doesn't exist, then we can simply return an alert coming from
00:02:50Â react-native.alert And we can give it a title of missing query and a message of please input something to search results across database.
00:03:01Â That way, if a user doesn't type anything, it should give us an alert.
00:03:05Â Next, outside of that if, if path name.
00:03:12Â dot starts with forward slash search.
00:03:17Â That means that we are already on the search page.
00:03:20Â And in that case, we simply want to set the search per RAM by saying router dot set per RAMs.
00:03:28Â And in an object, we set the query.
00:03:31Â Let's also import router from export router.
00:03:34Â And else, if we're not on the search, we want to say router.push and we want to push over to a template string of forward slash search,
00:03:44Â forward slash query.
00:03:46Â And now if you go in, click on this field, you're going to get this nice orange glow.
00:03:52Â And we can type something like, let's see, what do we have?
00:03:55Â AI maybe, AI and click search by pressing on the magnifying glass.
00:04:02Â You can see we are redirected to the search page and right now the text is not that visible.
00:04:09Â So let's make it a safe area view coming from react safe area view with a class name of BGPrimary and H-Fool.
00:04:21Â And now you can see that we have AI exactly like we typed.
00:04:25Â If you go back and type something like test, maybe, and press search, you can see that now we are on that page where the query is equal to search.
00:04:38Â That is great.
00:04:39Â That's enough information for us to be able to fetch all of the corresponding posts.
00:04:45Â With that in mind, let's head back to AppRight.
00:04:49Â and let's implement a function that searches through posts.
00:04:53Â To do that, we can duplicate the function that fetches the latest posts and rename it to searchPosts and it will accept the query as the first and only parameter.
00:05:06Â We do the same thing here.
00:05:08Â We call databases.listDocuments, provide the database ID and the collection ID of the documents we're trying to fetch.
00:05:15Â And then instead of order, we're going to use a query.search.
00:05:20Â We're going to search by title.
00:05:22Â and we're going to pass the query as the actual search term.
00:05:27Â Believe it or not, that is it.
00:05:30Â This should give us all the posts that match our corresponding query.
00:05:34Â That means that we can now go back to the query and call our useAppWriteHook to get all the necessary information.
00:05:41Â But if you look at our design, you'll notice that our search page is almost exactly the same as our homepage.
00:05:50Â It has the same search right here with the search term typed in already.
00:05:54Â It also has the heading and then it has the flat list.
00:05:58Â The only thing that's missing is the trending videos.
00:06:01Â So we'll basically be able to copy the homepage and make some slight modifications to implement the search page.
00:06:09Â So let's do exactly that.
00:06:11Â I'm going to head over to home.
00:06:13Â I'm going to copy the entire file.
00:06:16Â and I'll paste it into search.
00:06:19Â First things first, modify the component name or screen name from home to search.
00:06:26Â We can do that here.
00:06:27Â We don't need two different fetches.
00:06:29Â We need only one where we call the searchPosts function coming from libAppRide.
00:06:36Â And we also have to pass a query to it.
00:06:39Â And where do we get the query from?
00:06:41Â Well, we already know that.
00:06:42Â We have done it already.
00:06:44Â const query is equal to use local search params, which is coming directly from Expo router.
00:06:54Â import use local search params coming from Expo router.
00:07:01Â That way we get the query, then we use the useAppWrite hook to make a call to our search posts, and then we get posts right here.
00:07:11Â We also get this refetch, and we can refetch not by scrolling up, rather we can do a simple use effect right here with a callback function.
00:07:21Â which will be called every time that the query changes.
00:07:24Â So every time that the user types something new, we can just call a refetch function.
00:07:30Â Now, if we save this, of course, everything will be broken.
00:07:33Â First of all, we don't have this refreshing, so we can remove this bottom part.
00:07:37Â That's going to temporarily fix it.
00:07:40Â And let's navigate over to query to see how does that look like.
00:07:43Â I'm going to type AI and press search.
00:07:48Â And of course we get a couple of errors.
00:07:50Â First, we don't have the latest posts.
00:07:54Â which we pass over to trending so we can completely remove this view that says latest videos.
00:08:00Â But before we try to do another search, let's go ahead and see what other things we have to change.
00:08:05Â Starting from the top, we have a safe area view with a flat list that shows items vertically by default.
00:08:12Â We extract the IDs, we render the video card item, and then we list the header component.
00:08:18Â The header is not going to say welcome back, Rather, it will say something like search results and then below we can say query.
00:08:28Â So kind of giving search results for this specific query.
00:08:32Â And then right below this text, we don't even need this logo.
00:08:36Â We can immediately present our search input.
00:08:40Â So we have a text and immediately below that text, we can render our search input.
00:08:46Â This time we'll have to pass it an additional prop of initial query equal to query.
00:08:54Â That way we can accept it right here, initial query.
00:08:59Â And if we do have an initial query, we can set this query by default to be the initial query to auto-populate it.
00:09:08Â That way, if we come from home, it will be pre-populated to say the search term we searched for.
00:09:14Â Then let's see the structure here.
00:09:15Â We have one view with margin Y and padding X.
00:09:19Â We don't need the spacing here.
00:09:22Â And we don't need this entire inner view so we can close the opening and closing brace.
00:09:27Â We also don't need this opening view right here so we can remove it.
00:09:33Â And let's indent everything properly so it's easier to see.
00:09:36Â I'm going to make multiple selections and then do it like this.
00:09:40Â So we have the view, we have the text.
00:09:43Â that says search results immediately after we have a text that says query.
00:09:47Â And then below we want to have a view that will create some spacing with a class name of margin top of six and margin bottom of eight.
00:09:58Â And within it, we want to put the search input.
00:10:02Â There we go.
00:10:03Â And finally, we have the empty state, no videos found, but this time we can say something different like no videos found for this search query.
00:10:15Â See how good it is to make reusable components.
00:10:17Â We just have to change the prompt that we pass to it.
00:10:22Â With that in mind, let's give it a shot.
00:10:24Â Let's simply open up the keyboard and say AI and click search.
00:10:32Â As you can see, we are redirected directly to the search page, which looks great by default, but we also have to get rid of this top bar.
00:10:41Â I think we can do that within our primary layout.
00:10:45Â Yep.
00:10:45Â You can see here, stack search query.
00:10:48Â We have to uncomment this, which should get rid of the top bar.
00:10:52Â I think if you remove this forward slash, it will work.
00:10:55Â There we go.
00:10:55Â That's good.
00:10:57Â And we can immediately see the search results for the term AI.
00:11:01Â The AI is also pre-filled, but for some reason it says no videos found.
00:11:08Â That's interesting.
00:11:10Â So our searchPost function, this one, is not returning any videos that match by title.
00:11:18Â A quick way to debug it is to go here and check if AI is within some of these titles.
00:11:24Â And it does appear to be that way.
00:11:26Â Here we have a title of how AI shapes coding future.
00:11:30Â Inspired to code.
00:11:32Â I guess kind of code or COD is right here, code, and here is coding.
00:11:37Â So maybe if we try that, we should hit two of these videos.
00:11:40Â Let's give it a shot.
00:11:41Â I'm going to say COD.
00:11:43Â Start off code and coding, and still we get a possible unhandled promise rejection.
00:11:50Â Export default trending alert doesn't exist.
00:11:54Â This is actually quite good as we can just search for alert and see where it is being used.
00:12:00Â Sign in, sign up home.
00:12:03Â We're using it here, or at least we're importing it, but we're not using it.
00:12:07Â In the query, also not being used, we have this search input.
00:12:12Â Are we using it here?
00:12:13Â Yeah, it's coming from react native.
00:12:15Â That's looking good.
00:12:16Â And we have this use app right as well.
00:12:19Â Oh, it looks like we don't have it here.
00:12:21Â So here we have to import alert from react native.
00:12:25Â And once we do that, we get another error saying that the function is not defined, which is very useful because now we can go back to our,
00:12:34Â I believe it's query file.
00:12:37Â And it's basically saying that the search post is not defined.
00:12:41Â Even though it's coming from here and it does seem to be defined, we're also passing the query to it.
00:12:48Â Oh, this is a good one.
00:12:49Â So what I've done here is a typical rookie mistake.
00:12:53Â What we have done before is we're just passing the function to the useAppWrite, which we then later on call.
00:13:00Â It's similar if we pass, for example, get all posts right here.
00:13:05Â We pass the entire function declaration without calling it.
00:13:09Â That way, here, it gets replaced and it gets called.
00:13:13Â But what I've done now, since I had to pass the query, is I've actually called the function before.
00:13:20Â So instead of passing the function declaration, I'm passing whatever the output of this function is.
00:13:25Â For example, an array of some posts, right?
00:13:29Â And then that ends up getting all the way to here, and it tries to call an object, which is not possible.
00:13:37Â So if you need to pass some data into the function, when you're sending it over, you can do that by defining a callback function like this.
00:13:48Â It might be a bit harder to see, so I'm going to put it in a new line, use AppRight.
00:13:55Â Essentially you're passing the entire callback function.
00:13:57Â So once this gets called, the entire declaration will get passed and it will properly call it right here.
00:14:03Â I hope that makes sense.
00:14:06Â So now we can give it a second shot.
00:14:08Â Let's say something like AI and search.
00:14:14Â Okay, it says something like search for attribute title requires a full text index.
00:14:20Â And that means that we have to go right here to databases, go to the videos collection and go to indices and create a new index.
00:14:31Â We can call it something like search by title.
00:14:36Â The index type will be full text as the error message said, and the attribute will be by title.
00:14:42Â And let's click create.
00:14:44Â It looks like the index name needs to be properly indexable.
00:14:47Â So let's do search underscore by underscore title and click create.
00:14:53Â There we go.
00:14:54Â The index was created and this should allow us to do searches.
00:14:58Â Back in the code, I will type ai one last time.
00:15:04Â And this time we don't get an error, which is great, but we also don't see any videos.
00:15:10Â So what we could do is we could console log a couple of things.
00:15:15Â We can console log first of all, the query to see if the query is good.
00:15:19Â And then the posts that we got back to see if there is anything to show.
00:15:25Â Once we do that, you can see that the query was all right, but the array was empty.
00:15:30Â Let's try to search for something like COD for coding.
00:15:36Â And this time we do get back to videos, the how AI shapes coding future and get inspired to code, which is exactly what I wanted to get back.
00:15:46Â Interesting how it didn't get us AI.
00:15:48Â Let's try one more time.
00:15:50Â No.
00:15:51Â What if we do both letters uppercased?
00:15:55Â What if we do Italy?
00:15:56Â I know that's another word from our titles.
00:16:01Â Okay.
00:16:01Â That works.
00:16:02Â That's interesting.
00:16:03Â Maybe it's trying to search for more than two characters.
00:16:07Â Let's see.
00:16:07Â What else do we have here?
00:16:09Â Inspired, journey.
00:16:11Â Let's search for inspired.
00:16:14Â That is great.
00:16:16Â And let's also search for journey.
00:16:23Â Perfect.
00:16:24Â Basically everything is working, but for some reason search for AI didn't work.
00:16:29Â But at least that showed us that our no videos screen is working as we get no videos found and then create video.
00:16:37Â So that is great.
00:16:38Â Let's go back to homepage one more time.
00:16:40Â We can see different posts.
00:16:42Â We can see the latest videos as well.
00:16:44Â And we can make a search and you get a complete search similar to the homepage.
00:16:51Â But in this new layout where you can keep searching for whatever you want to find by simply deleting it and searching again,
00:16:57Â or you can swipe left to go back to home.
00:17:01Â Wonderful.
00:17:02Â It wasn't that tough to create search once we have reusable video card components, reusable flat lists, and also reusable hooks that allow us to more easily
00:17:11Â fetch data.
00:17:12Â We can also clean things up a bit as our query is a bit smaller than our homepage.
00:17:16Â We don't need things like the image, refresh control, or alert.
00:17:20Â We don't need to use state, images, trending, and all of these other calls from AppRide.
00:17:27Â I always like to keep my code clean and have zero unused variables.