Reputation: 2562
I am making a small React App that getting data from a Countries Api. I want to use the Select tag in React. This is so that I can filter the regions of the countries on the page. So if someone selects Europe it returns European Countries, or Africa then African countries and so on. I have looked at this post for using the select tag . However, the issue I have is that the list keeps repeating itself.
Below is the code that I have so far:
import React, { Component } from 'react';
import { CountryList } from './Components/Card-List/CountryList';
import { SearchBox } from './Components/Search-box/Search-Box';
import { NavBarCard }from './Components/NavBar/NavBarCard';
import './Countries.styles.css';
class Countries extends Component {
constructor() {
super();
this.state = {
countries:[],
searchField:"",
regionField:"",
darkMode: false
}
this.setDarkMode = this.setDarkMode.bind(this);
// this.handleRegion = this.handleRegion.bind(this);
};
componentDidMount() {
fetch("https://restcountries.eu/rest/v2/all")
.then(response => response.json())
.then(all => this.setState({ countries: all,
regions: all}))
}
setDarkMode(e){
this.setState((prevState) => ({ darkMode: !prevState.darkMode }));
}
handleRegion = (e) => {
this.setState({regionField: e.target.value})
}
render() {
const { countries, searchField, regionField, darkMode } = this.state;
const filterCountries = countries.filter((country) => country.name.toLowerCase().includes(searchField.toLowerCase()) &&
country.region.toLowerCase().includes(regionField.toLowerCase()));
return(
<div className={darkMode ? "dark-mode" : "light-mode" }>
<NavBarCard handlechange={this.setDarkMode} moonMode={darkMode ? "moon fas fa-moon" : "moon far fa-moon"} darkMode={darkMode ? "dark-mode" : "light-mode"}/>
<div className="Input">
< SearchBox type="search" placeholder="Search a Country" handlechange={e=> this.setState({
searchField: e.target.value })}
/>
{/* < SearchBox type="regions" placeholder="Filter by Regions" handlechange={e=> this.setState({
regionField: e.target.value })}
/> */}
<select onChange={this.handleRegion}>
{countries.map(region => (
<option key={region.alpha2Code}>
{region.region}
</option>
))}
</select>
</div>
<CountryList countries={filterCountries} />
</div>
)
}
}
export default Countries
Not sure what I have missed. Any help would be appreciated.
Upvotes: 0
Views: 1016
Reputation: 1
You're passing Countries to this <CountryList countries={filterCountries} />
.
I hope you're not looping to render the countries in this component.
This:
<select onChange={this.handleRegion}>
{countries.map(region => (
<option key={region.alpha2Code}>
{region.region}
</option>
))}
</select>
is correct but you need to add value attribute <select onChange {this.handleRegion} value={regionField}>
Also uncomment the binding with the this
keyword in the constructor for handleRegion
method.
Edited
let regions = [];
fetch("https://restcountries.eu/rest/v2/all")
.then(response => response.json())
.then(all => {
// Get unique regions here using Set
let uniqueRegions = new Set();
all.forEach(item => {
uniqueRegions.add(item.region);
});
for (item of uniqueRegions) {
regions.push(item);
};
this.setState({
countries: all,
regions: regions
})
});
Upvotes: 0
Reputation: 312
It´s clear that your problem is not in the code itself, it is the way you handle the data. You are mapping the countries array, so for each country there is a region field in it. What you are getting back in the select tag is all the countries but instead of showing their names they are showing the region they belong to.
Upvotes: 2