AltBrian
AltBrian

Reputation: 2562

Map function keeps repeating the output

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.enter image description here

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

Answers (2)

Isah Ohieku
Isah Ohieku

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

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

Related Questions