'website breaks when trying to .map through two select filters

I am creating a website with custom cards to displays companys and a sidebar filter. The data comes from an Array of Objects (Datalist.js). My problem is that the website breaks as soon as I try to loop through crypto. The problem does not exist with country.

I assume it happens because (crypto is an object in the object) and therefore .map doesn't work because its only for arrays.

any tips?

Datalist.js

export const data = [
    {
        id:1,
        name:"Digitec",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Onlineshop besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"E-commerce"
    },
    {
        id:2,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Immobilien"
    },
    {
        id:3,
        name:"Unplugged Performance",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"unplugged.jpg",
        website:"https://unpluggedperformance.com/",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            ltc:"ltc.png",
        },
        country: "Amerika",
        tag:"Automobil"
    },
    {
        id:4,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Automobil"
    },
    {
        id:5,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Gastronomie"
    },
    {
        id:6,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
            xmr:"xmr.png",
        },
        country: "Schweiz",
        tag:"Lebensmittelhändler"
    },
    {
        id:7,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Lebensmittelhändler"
    },
    {
        id:8,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Medizin"
    },
    {
        id:9,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            eth:"eth.png",
            doge:"doge.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Gastronomie"
    },
    {
        id:10,
        name:"Galaxus",
        description:"wir akzeptieren folgende Kryptowährungen als Zahlungsmittel:",
        logo:"brack.jpg",
        website:"https://www.galaxus.ch/de",
        forward:"Webseite besuchen",
        crypto: {
            btc:"btc.png",
            doge:"doge.png",
            eth:"eth.png",
            usdt:"usdt.png",
        },
        country: "Schweiz",
        tag:"Medizin"
    },
]

FilterBar.js

import React, {useState} from 'react'

function FilterBar({countries, cryptos, onNameFilter, onCountryFilter, onCryptoFilter}) {
    const [filters, setFilters] = useState({
        name: "",
        country: "",
        crypto: "",
    });

    const handleInput = (field) => (event) => {
        const {value} = event.target;

        setFilters({
            ...filters,
            [field]: value,
        })

        switch(field) {
            case "name":
                onNameFilter(value);
                break;
            case "country":
                onCountryFilter(value);
                break;
            case "crypto":
                onCryptoFilter(value);
                break;
            default:
                break;
        }
    };

    return (
        <div className="row my-5">
            <div className="col sticky">
                <h4 className="border-bottom">Filters</h4>
            </div>
            <div className="col-sm-12 my-2">
                <input 
                type="text" 
                className="forms-control" 
                id="name"
                value={filters.name}
                placeholder="company name"
                onChange={handleInput ("name")}
                ></input>
            </div>

            <div className="col-sm-12 my-2">
                <label htmlFor="country">country</label>
                <select className="form-control" id="country" onChange={handleInput ("country")}>
                    <option value="select">Select</option>
                    {countries.map((country) => (
                        <option value={country} key={country}>{country}</option>
                    ))}
                </select>
            </div>

            <div className="col-sm-12 my-2">
                <label htmlFor="crypto">Cryptocurreny</label>
                <select className="form-control" id="crypto" onChange={handleInput ("crypto")}>
                    <option value="select">Select</option>
                    {cryptos.map((crypto) => (
                        <option value={crypto} key={crypto}>{crypto}</option>
                    ))}
                </select>
            </div>
        </div>
    )
}

export default FilterBar

PersonItem.js

import React from 'react'

function PersonItem({item}) {
    return (
        <div className="col-sm-12 col-md-4">
            <div className="card-my-2 text-center">
                <img src={item?.image} className="card-img-top" alt="" />
                <div className="card-body">
                    <h5 className="card-title">
                        {item?.name}
                    </h5>
                    <h5 className="card-description">{item?.description}</h5>
                    {Object.values(item.crypto).map((imgName, index) => (
                        <img key={index}
                        className="cryptoImg"
                        alt="crypto"
                        variant="top"
                        src={`./images/${imgName}`} />
                    ))}
                    <button className="card-text" src={item?.website}>Shop besuchen</button>
                </div>
            </div>
        </div>
    )
}

export default PersonItem

App.js

import {useState} from "react";
import './App.css';
import {data} from "./Datalist";
import FilterBar from "./components/FilterBar";
import PersonItem from './components/PersonItem';

function App() {
  const [allData, setAllData] = useState(data);

  /*generating new Array with filtered data for country dropdown*/
  const generateCountryDataForDropdown = () => {
    return [...new Set(data.map((item) => item.country))];
  };


  /*generating new Array with filtered data for currency dropdown*/
  const generateCryptoDataForDropdown = () => {
    return [...new Set(data.map((item) => item.crypto))];
  };




  /*filter name function*/
  const handleFilterName = (event) => {
    const filteredData = data.filter((item) => {
      if (item.name.toLowerCase().includes(event.toLowerCase())) {
        return item;
      }
    });

    setAllData(filteredData);
  };


  /*filter country function*/
  const handleFilterCountry = (country) => {
    const filteredData = data.filter((item) => {
      if (item.country === country) {
        return country;
      }
    });

    setAllData(filteredData);
  };


  /*filter crypto function*/
  const handleFilterCrypto = (crypto) => {
    const filteredData = data.filter((item) => {
      if (item.crypto === crypto) {
        return crypto;
      } 
    });

    setAllData(filteredData);
  };

  return (
    <div className="container">
      <div className="row">
        <div className="col-sm-3">
          <FilterBar 
          countries={generateCountryDataForDropdown()}
          cryptos={generateCryptoDataForDropdown()}
           
          onNameFilter={handleFilterName} 
          onCountryFilter={handleFilterCountry}
          onCryptoFilter={handleFilterCrypto}
          />
        </div>
        <div className="col-sm-9">
          <div className="row mt-5">
            {allData.map((item) => (
              <PersonItem item={item} key={item.id} />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

export default App;


Solution 1:[1]

In your app.js [...new Set(data.map((item) => item.crypto))] will return an array of objects.

So in FilterBar.js you cant give

 {cryptos.map((crypto) => (
     <option value={crypto} key={crypto}>{crypto}</option>
  ))}

because crypto is object with keys btc,doge etc.

You could try

Object.keys(cryptos).map((crypto) => (
     <option value={crypto} key={crypto}>{crypto}</option>
  ))}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rahuuzz