I'm working on a frontend mentor challenge and I'm trying to filter the array from an Api by select
and input
, The array is being filtered when i use the search bar for searching but its not displaying anything when i use the select
tag
const Home = () => {
const [countryData, setCountryData] = useState([])
const [list, setList] = useState([])
const [select, setSelect] = useState("All")
const [searchText, setSearchText] = useState('')
useEffect(() => {
fetch('https://restcountries.com/v3.1/all')
.then (response => response.json())
.then (data => setCountryData(data))
}, [])
const handleChange = (e) => {
setSelect(e.target.value)
console.log(e.target.value)
}
const filteredCountries = () => {
const filterer = countryData.filter(item => {
if(searchText.length < 1 && select === "All"){
return item.region === "Africa" || "Americas" || "Oceania" || "Asia" || "Europe"
}
else if(searchText.length > 2 && item.region === "Africa" || "Americas" || "Oceania" || "Asia" || "Europe" || "All"){
return item.name.official.includes(searchText)
}
return item.region === select
})
setList(filterer)
}
useEffect(()=> {
filteredCountries()
}, [searchText, select])
return (
<div className=" h-100vh">
<div className="flex mt-8 justify-between px-14 items-center">
<div className='flex items-center h-10 bg-navcol w-1/3'>
<FaSearch/>
<input value={searchText} onChange={(e) => setSearchText(e.target.value)} className="bg-transparent w-full text-xs text-white focus:border-none hover:border-none active:border-none" placeholder='Search for a country...'/>
</div>
<select value = {select} onChange={handleChange} className="w-32 active:border-none bg-navcol focus:border-none h-10 text-xs text-white" placeholder='chhose o'>
<option value ="Africa">Africa</option>
<option value ="Americas">America</option>
<option value ="Asia">Asia</option>
<option value ="Europe">Europe</option>
<option value ="Oceania">Oceanic</option>
<option value ="All" defaultValue= {true} >Filter by Region</option>
</select>
</div>
<CountriesList data = {list}/>
</div>
)
}
CodePudding user response:
Your if-else constructions are not ok. The main reason is bellow
//your code always evaluates to true. You can put a console log within it. So if you change the region it searches by searchText
else if(searchText.length > 2 && item.region === "Africa" || "Americas" || "Oceania" || "Asia" || "Europe" || "All"){
return item.name.official.includes(searchText)
}
Even though I am not sure what behavior you expected - I made a stack-blitz demo: working-demo-code
CodePudding user response:
First of all change the input classnames from text-white to text-black to make text visible while entering data.
Second thing in your CountriesList component you should map the data as follows:
const CountriesList = ({ data }) => {
return (
<div>
{data.map((item) => (
<p>{item.name.common}</p>
))}
</div>
)
}
I don't think your logic for filtering the countries with region is correct because it is returning all the 250 countries after selecting a region from drop down list. But it is correctly filtering counties by Search input.
I think for what you want to achieve the code should look something like below:
Home.js
import React, { useEffect, useState } from 'react'
import CountriesList from './CountriesList'
const Home = () => {
const [countryData, setCountryData] = useState([])
const [list, setList] = useState([])
const [select, setSelect] = useState('All')
const [searchText, setSearchText] = useState('')
useEffect(() => {
fetch('https://restcountries.com/v3.1/all')
.then((response) => response.json())
.then((data) => setCountryData(data))
}, [])
const handleChange = (e) => {
setSelect(e.target.value)
console.log(e.target.value)
}
const filteredCountries = () => {
const filterer = countryData.filter((item) => {
if (searchText.length < 1) {
return item.region === select
} else if (searchText.length > 2) {
return item.name.official.includes(searchText)
}
})
console.log('This is filterer >>>', filterer)
setList(filterer)
}
useEffect(() => {
filteredCountries()
}, [searchText, select])
return (
<div className=" h-100vh">
<div className="flex mt-8 justify-between px-14 items-center">
<div className="flex items-center h-10 bg-navcol w-1/3">
<input
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
className="w-full text-xs text-black focus:border-none hover:border-none active:border-none"
placeholder="Search for a country..."
/>
</div>
<select
value={select}
onChange={handleChange}
className="w-32 active:border-none bg-navcol focus:border-none h-10 text-xs text-black"
placeholder="chhose o"
>
<option value="Africa">Africa</option>
<option value="Americas">America</option>
<option value="Asia">Asia</option>
<option value="Europe">Europe</option>
<option value="Oceania">Oceanic</option>
<option value="All" defaultValue={true}>
Filter by Region
</option>
</select>
</div>
<CountriesList data={list} />
</div>
)
}
export default Home
CountriesList.js
import React from 'react'
const CountriesList = ({ data }) => {
return (
<div>
{data.map((item) => (
<p>{item.name.common}</p>
))}
</div>
)
}
export default CountriesList