Reputation: 29
Here is a link to my app on Codesandbox https://codesandbox.io/s/filter-search-gxidc?file=/src/App.js it's only one component app.js
In data.js I have an array of objects:
export const data = [
{
currencies: [{ code: "AFN", name: "Afghan afghani", symbol: "؋" }],
languages: [
{ iso639_1: "ps", iso639_2: "pus", name: "Pashto", nativeName: "پښتو" },
{ iso639_1: "uz", iso639_2: "uzb", name: "Uzbek", nativeName: "Oʻzbek" },
{
iso639_1: "tk",
iso639_2: "tuk",
name: "Turkmen",
nativeName: "Türkmen"
}
],
flag: "https://restcountries.eu/data/afg.svg",
name: "Afghanistan",
topLevelDomain: [".af"],
capital: "Kabul",
region: "Asia",
subregion: "Southern Asia",
population: 27657145,
borders: ["IRN", "PAK", "TKM", "UZB", "TJK", "CHN"],
nativeName: "افغانستان"
},
{
currencies: [{ code: "EUR", name: "Euro", symbol: "€" }],
languages: [
{
iso639_1: "sv",
iso639_2: "swe",
name: "Swedish",
nativeName: "svenska"
}
],
flag: "https://restcountries.eu/data/ala.svg",
name: "Åland Islands",
topLevelDomain: [".ax"],
capital: "Mariehamn",
region: "Europe",
subregion: "Northern Europe",
population: 28875,
borders: [],
nativeName: "Åland"
},
{
currencies: [{ code: "ALL", name: "Albanian lek", symbol: "L" }],
languages: [
{ iso639_1: "sq", iso639_2: "sqi", name: "Albanian", nativeName: "Shqip" }
],
flag: "https://restcountries.eu/data/alb.svg",
name: "Albania",
topLevelDomain: [".al"],
capital: "Tirana",
region: "Europe",
subregion: "Southern Europe",
population: 2886026,
borders: ["MNE", "GRC", "MKD", "KOS"],
nativeName: "Shqipëria"
},
{
currencies: [{ code: "DZD", name: "Algerian dinar", symbol: "د.ج" }],
languages: [
{ iso639_1: "ar", iso639_2: "ara", name: "Arabic", nativeName: "العربية" }
],
flag: "https://restcountries.eu/data/dza.svg",
name: "Algeria",
topLevelDomain: [".dz"],
capital: "Algiers",
region: "Africa",
subregion: "Northern Africa",
population: 40400000,
borders: ["TUN", "LBY", "NER", "ESH", "MRT", "MLI", "MAR"],
nativeName: "الجزائر"
},
{
currencies: [{ code: "USD", name: "United State Dollar", symbol: "$" }],
languages: [
{
iso639_1: "en",
iso639_2: "eng",
name: "English",
nativeName: "English"
},
{
iso639_1: "sm",
iso639_2: "smo",
name: "Samoan",
nativeName: "gagana fa'a Samoa"
}
],
flag: "https://restcountries.eu/data/asm.svg",
name: "American Samoa",
topLevelDomain: [".as"],
capital: "Pago Pago",
region: "Oceania",
subregion: "Polynesia",
population: 57100,
borders: [],
nativeName: "American Samoa"
},
{
currencies: [{ code: "EUR", name: "Euro", symbol: "€" }],
languages: [
{ iso639_1: "ca", iso639_2: "cat", name: "Catalan", nativeName: "català" }
],
flag: "https://restcountries.eu/data/and.svg",
name: "Andorra",
topLevelDomain: [".ad"],
capital: "Andorra la Vella",
region: "Europe",
subregion: "Southern Europe",
population: 78014,
borders: ["FRA", "ESP"],
nativeName: "Andorra"
},
{
currencies: [{ code: "AOA", name: "Angolan kwanza", symbol: "Kz" }],
languages: [
{
iso639_1: "pt",
iso639_2: "por",
name: "Portuguese",
nativeName: "Português"
}
],
flag: "https://restcountries.eu/data/ago.svg",
name: "Angola",
topLevelDomain: [".ao"],
capital: "Luanda",
region: "Africa",
subregion: "Middle Africa",
population: 25868000,
borders: ["COG", "COD", "ZMB", "NAM"],
nativeName: "Angola"
}
];
I wanna map through it and display information about each country (I did this part ) at app.js
here is the code in app.js
import React, { useState, useEffect } from "react";
import "./styles.css";
import { data } from "./data";
export default function App() {
const [cuntries, setCountries] = useState([]);
const [region, setRegion] = useState('');
useEffect(()=>{
setCountries(data)
},[])
function filterByRegion(event) {
setRegion(event.target.value);
handleSubmit()
// event.preventDefault()
}
function handleSubmit(){
const newArr = cuntries.filter(cunt=> cunt.region === region)
setCountries(newArr)
}
console.log(region);
console.log(cuntries);
return (
<div className="App">
<h1>filtering</h1>
<form onChange={filterByRegion}>
<label>Filter by region:</label>
<select name="regions" id="region-select" >
<option value="">Chose a region</option>
<option value="Africa">Africa</option>
<option value="Americas">Americas</option>
<option value="Asia">Asia</option>
<option value="Oceania">Oceania</option>
<option value="Polar">Polar</option>
</select>
</form>
<div>
{cuntries.map((country) => {
return (
<div key={country.name} className="country">
<h3>{country.name}</h3>
<h3>{country.nativeName}</h3>
<h3>{country.region}</h3>
</div>
);
})}
</div>
</div>
);
}
In app.js I have a select element that contains regions I wanna filter the array that I used to render each country So that when I choose a different region the map method render the countries that in this region
I tried some solution but non of them worked.
the link to the app again https://codesandbox.io/s/filter-search-gxidc?file=/src/App.js:0-1424
Upvotes: 0
Views: 317
Reputation: 15166
The main problem could be setRegion
is handled asynchronously so once you try to filter further by its value in handleSubmit
then the value is most probably not there. See down below the suggested modifications on your component.
The first thing is to add onChange
event to select
instead of form
:
<select name="regions" id="region-select" onChange={filterByRegion}>
<option value="">Chose a region</option>
<option value="Africa">Africa</option>
<option value="Americas">Americas</option>
<option value="Asia">Asia</option>
<option value="Oceania">Oceania</option>
<option value="Polar">Polar</option>
</select>
Modify filterRegion
to pass down the value to handleSubmit
as:
const filterByRegion = (event) => {
const region = event.target.value
// I would keep this state if you really need for other purposes
setRegion(region)
handleSubmit(region)
}
Then I would use with .filter
the data
as the original array to find values as:
const handleSubmit = (regionValue) => {
const newArr = data.filter(c => c.region === regionValue)
setCountries(newArr)
}
Please find the working CodeSandbox here.
+1 addition:
If you want to render something for no values found state for you countries:
{cuntries && cuntries.length > 0 ?
cuntries.map((country) => {
return (
<div key={country.name} className="country">
<h3>{country.name}</h3>
<h3>{country.nativeName}</h3>
<h3>{country.region}</h3>
</div>
);
})
: <div>No value found</div>
}
So if there are no values in your countries
array you can render a <div>
which states there are no values found.
Upvotes: 0