Home > other >  I'm trying to filter by select and search
I'm trying to filter by select and search

Time:10-03

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
  • Related