Add Search filter in NextJs
using useState
and useEffect
import Layout from "../../components/Layout";
import { NextSeo } from "next-seo";
import { useState, useEffect } from "react";
import CitiesComponent from "../../components/CitiesComponent";
const topCity = () => {
/**
* get all cities array
*/
const [cities, setCities] = useState([]);
/**
* loding indicator
*/
const [loading, setLoading] = useState(false);
/**
* input field keyword onchage
*/
const [search, setSearch] = useState("");
/**
* loop over the cities
*/
const [filteredCities, setFilteredCities] = useState([]);
/**
* Fetch api
*/
useEffect(() => {
setLoading(true);
fetch(`https://restcountries.eu/rest/v2/all`)
.then((res) => res.json())
.then((data) => {
setCities(data);
setLoading(false);
})
.catch((err) => {
console.log(err);
});
}, []);
/**
* fetch this effect while entering the keywords
*/
useEffect(() => {
setFilteredCities(
cities.filter((city) =>
city.name.toLowerCase().includes(search.toLowerCase())
)
);
}, [search, cities]);
if (loading) {
return <div>Loading...</div>;
}
return (
<Layout>
<NextSeo
title={`Top cities`}
description={`Top cities `}
openGraph={{
title: `Top cities`,
description: `Top cities `,
}}
/>
<input
type="text"
placeholder="Search Cities"
onChange={(e) => setSearch(e.target.value)}
/>
<div className="flex">
<div className="w-screen mb-5 px-4 md:px-5">
<div className="flex flex-wrap -mx-1 lg:-mx-4">
{filteredCities.map((city, ids) => (
<CitiesComponent key={ids} {...city} />
))}
</div>
</div>
</div>
</Layout>
);
};
export default topCity;
component CitiesComponent.js
import Link from 'next/link';
const CitiesComponent = ( props ) => {
const {name, flag} = props;
return (
<div
key={name}
className="px-1 w-full md:w-1/2 lg:my-2 lg:px-4 lg:w-1/6"
>
<Link href={`/countries/${name}`}>
<a
className="shover:underline hover:text-blue-500"
target="_blank"
rel="noopener noreferrer"
>
{name}
</a>
</Link>
</div>
)
}
export default CitiesComponent