Search Filter in NextJS

Ryan Mambou
4 min readSep 29, 2022

--

Have you ever wondered on how to make search results instantly available while still typing on the search bar in websites ? It seems quite complex. Guess what ? It’s not as complicated as it seems and you can achieve this with no API call from the server.

Instead, the result above is achieved by using a search filter.

But what is a search filter ? Calm down. It’s just a function where we’ll apply basic JavaScript logic.

For a better understanding, let’s build the app above.

The project is from Frontend Mentor’s Advanced API project.

  1. Setting up our NextJS project
npx create-next-app restcountries
cd restcountries
npm run dev

2. Installing TailwindCSS for styling

I’ll recommend you to see the official documentation for thorough explanation on its intallation.

3. Fetching Data from API

Now that our project is set, let’s use the getStaticProps() function by NextJS to pre render our content from the API. If you’re not familiar with pre-rendering, I have an article on that.

The structure of what we’ll get from the API is as follows:

{"name": {
"common": "Guatemala",
"official": "Republic of Guatemala",
"nativeName": {
"spa": {
"official": "República de Guatemala",
"common": "Guatemala"
}
}
},
"tld": [
".gt"
],
"cca2": "GT",
"ccn3": "320",
"cca3": "GTM",
"cioc": "GUA",
"independent": true,
"status": "officially-assigned",
"unMember": true,
"currencies": {
"GTQ": {
"name": "Guatemalan quetzal",
"symbol": "Q"
}
},
"idd": {
"root": "+5",
"suffixes": [
"02"
]
},
"capital": [
"Guatemala City"
],
"altSpellings": [
"GT"
],
"region": "Americas",
"subregion": "Central America",
"languages": {
"spa": "Spanish"
},
"translations": {
"ara": {
"official": "جمهورية غواتيمالا",
"common": "غواتيمالا"
},
"bre": {
"official": "Republik Guatemala",
"common": "Guatemala"
},
"ces": {
"official": "Republika Guatemala",
"common": "Guatemala"
},
"cym": {
"official": "Republic of Guatemala",
"common": "Guatemala"
},
"deu": {
"official": "Republik Guatemala",
"common": "Guatemala"
},
"est": {
"official": "Guatemala Vabariik",
"common": "Guatemala"
},
"fin": {
"official": "Guatemalan tasavalta",
"common": "Guatemala"
},
"fra": {
"official": "République du Guatemala",
"common": "Guatemala"
},
"hrv": {
"official": "Republika Gvatemala",
"common": "Gvatemala"
},
"hun": {
"official": "Guatemalai Köztársaság",
"common": "Guatemala"
},
"ita": {
"official": "Repubblica del Guatemala",
"common": "Guatemala"
},
"jpn": {
"official": "グアテマラ共和国",
"common": "グアテマラ"
},
"kor": {
"official": "과테말라 공화국",
"common": "과테말라"
},
"nld": {
"official": "Republiek Guatemala",
"common": "Guatemala"
},
"per": {
"official": "جمهوری گواتِمالا",
"common": "گواتِمالا"
},
"pol": {
"official": "Republika Gwatemali",
"common": "Gwatemala"
},
"por": {
"official": "República da Guatemala",
"common": "Guatemala"
},
"rus": {
"official": "Республика Гватемала",
"common": "Гватемала"
},
"slk": {
"official": "Guatemalská republika",
"common": "Guatemala"
},
"spa": {
"official": "República de Guatemala",
"common": "Guatemala"
},
"swe": {
"official": "Republiken Guatemala",
"common": "Guatemala"
},
"tur": {
"official": "Guatemala Cumhuriyeti",
"common": "Guatemala"
},
"urd": {
"official": "جمہوریہ گواتیمالا",
"common": "گواتیمالا"
},
"zho": {"official": "危地马拉共和国",
"common": "危地马拉"
}
},
"latlng": [
15.5,
-90.25
],
"landlocked": false,
"borders": ["BLZ",
"SLV",
"HND",
"MEX"
],
"area": 108889.0,
"demonyms": {
"eng": {
"f": "Guatemalan",
"m": "Guatemalan"
},
"fra": {
"f": "Guatémaltèque",
"m": "Guatémaltèque"
}
},
"flag": "🇬🇹",
"maps": {
"googleMaps": "https://goo.gl/maps/JoRAbem4Hxb9FYbVA",
"openStreetMaps": "https://www.openstreetmap.org/relation/1521463"
},
"population": 16858333,
"gini": {
"2014": 48.3
},
"fifa": "GUA",
"car": {
"signs": [
"GCA"
],
"side": "right"
},
"timezones": [
"UTC-06:00"
],
"continents": [
"North America"
],
"flags": {
"png": "https://flagcdn.com/w320/gt.png",
"svg": "https://flagcdn.com/gt.svg"
},
"coatOfArms": {
"png": "https://mainfacts.com/media/images/coats_of_arms/gt.png",
"svg": "https://mainfacts.com/media/images/coats_of_arms/gt.svg"
},
"startOfWeek": "monday",
"capitalInfo": {
"latlng": [
14.62,
-90.52
]
},
"postalCode": {
"format": "#####",
"regex": "^(\\d{5})$"
}
},

Before we do anything, let’s install axios to fetch data from the server.

npm install axios

Then, let’s copy and paste the following code in our index.js page located inside the page folder:

fetching data

NB: The class names you see are default classes implemented by Tailwind

Now that we’ve successfully displayed our data, let’s concentrate on implementing our search filter.

4. Implementing our Search Filter

The function for our filter is as follows:

const filterdByRegion = (array) => {
return array.filter(el => el.name.common.toLowerCase().includes(query))}

This function takes an array as a parameter, loops through it and returns elements that satisfies the condition element.name.common.toLowerCase().includes(query)

NB:

  • toLowerCase() is to ensure the value from accessing data from the API is in the same format with that in our search bar (as we are typing in lowercase)
  • query is the value of what we type in the search bar. This is handled by he handleChange() function.
  • includes() is a JavaScript function that returns true if a string contains a specific string or false otherwise

Now, our index.js page should look as follows:

Implementing search filter

We’re done, we’ve just implemented our search filter. You see it’s not much of a big deal.

If you have any question you can check on me on my Twitter, I’ll be happy to clear any doubt.

A live demo of the project can be found here

You may leave a clap if you enjoyed. Stay hard!

--

--