Filter array data and return it Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Filter array data and return it without wasting too much if your time.

The question is published on by Tutorial Guruji team.

This should be some silly mistake I am doing, but I can’t find the problem.

I am making an application that gets an array from the server, then, I display the received data filtered by the user input serch.

If only one country is found in the search, the information for that country is displayed.

if (filteredCountries.length === 1) {
  return filteredCountries.map((country) => (
    <p key={country.alpha2Code}>
      Capital: {country.capital}. Population: {country.population} <img src={country.flag} />
    </p>
  ));
}

If several countries are found (but less than 10), a list of them is displayed, with a button beside each country on the list, that if clicked, shows the information from that specific country, using the method handleClick.

if (filteredCountries.length > 0 && filteredCountries.length < 10 && filteredCountries.length > 1) {
  return filteredCountries.map((country) => (
    <p key={country.alpha2Code}>
      {country.name}
      {<button onClick={handleClick}>show</button>}
    </p>
  ));
}

handleClick should take as a prop the specific country, and display the data for that specific country. But it is not working for me.

const handleClick = (country) => {
  console.log('click');
  console.log(country);
  return filteredCountries.map((country) => (
    <p key={country.alpha2Code}>
      Capital: {country.capital}. Population: {country.population} <img src={country.flag} />
    </p>
  ));
};

What am I missing here?

Full code Code sandbox

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const App = () => {
  const [countries, setCountries] = useState([]);

  const [searchFilter, setSearchFilter] = useState('');

  const hook = () => {
    console.log('effect');
    axios.get('https://restcountries.eu/rest/v2/all').then((response) => {
      console.log('promise fulfilled');
      setCountries(response.data);
    });
  };

  useEffect(hook, []);

  console.log('render', countries.length, 'countries');
  console.log(countries);

  const handleClick = (country) => {
    console.log('click');
    console.log(country);
    return filteredCountries.map((country) => (
      <p key={country.alpha2Code}>
        Capital: {country.capital}. Population: {country.population} <img src={country.flag} />
      </p>
    ));
  };

  const filteredCountries =
    searchFilter.length === 1
      ? countries
      : countries.filter((country) => country.name.toLowerCase().indexOf(searchFilter.toLowerCase()) > -1);

  const showCountries = () => {
    if (filteredCountries.length > 10) {
      return 'Too many matches, keep on typing';
    }

    if (filteredCountries.length > 0 && filteredCountries.length < 10 && filteredCountries.length > 1) {
      return filteredCountries.map((country) => (
        <p key={country.alpha2Code}>
          {country.name}
          {<button onClick={handleClick}>show</button>}
        </p>
      ));
    }
    if (filteredCountries.length === 1) {
      return filteredCountries.map((country) => (
        <p key={country.alpha2Code}>
          Capital: {country.capital}. Population: {country.population} <img src={country.flag} />
        </p>
      ));
    }
  };
  const searchHandler = (e) => {
    setSearchFilter(e.target.value);
  };

  return (
    <div>
      <div>
        <h1>Countries</h1>
      </div>
      <div>
        Type to find countries:
        <input onChange={searchHandler} />
        <div>{showCountries()}</div>
      </div>
    </div>
  );
};

export default App;

Answer

You shouldn’t return any view in the handle click. Instead, track the selected country on the click of show button and based on that selection render the country view.

Try this approach,

import React, { useState, useEffect } from "react";
import axios from "axios";
//setCountries is a function for setting the country's state
const App = () => {
  const [countries, setCountries] = useState([]);
  //Filter
  const [searchFilter, setSearchFilter] = useState("");

  const [selectedCountry, setSelectedCountry] = useState("");

  const hook = () => {
    console.log("effect");
    axios.get("https://restcountries.eu/rest/v2/all").then((response) => {
      console.log("promise fulfilled");
      setCountries(response.data);
    });
  };

  useEffect(hook, []);
  /*   by default the effect is always run after the component has been rendered. In our case, however, we only want to execute the effect along with the first render.

  The second parameter of useEffect is used to specify how often the effect is run. If the second parameter is an empty array [], then the effect is only run along with the first render of the component. */

  console.log("render", countries.length, "countries");
  console.log(countries);

  const renderCountryDetails = () => {
    return (
      selectedCountry && (
        <p key={selectedCountry.alpha2Code}>
          Capital: {selectedCountry.capital}. Population:{" "}
          {selectedCountry.population} <img src={selectedCountry.flag} />
        </p>
      )
    );
  };

  const filteredCountries =
    searchFilter.length === 1
      ? countries
      : countries.filter(
          (country) =>
            country.name.toLowerCase().indexOf(searchFilter.toLowerCase()) > -1
        );

  //showCountries returns either a message or else the contents of filteredcountries array
  const showCountries = () => {
    /* if (filteredCountries.length === 0) {
    return 'No coincidences found'  
} */
    if (filteredCountries.length > 10) {
      return "Too many matches, keep on typing";
    }

    if (
      filteredCountries.length > 0 &&
      filteredCountries.length < 10 &&
      filteredCountries.length > 1
    ) {
      return (
        <div>
          {filteredCountries.map((country) => (
            <p key={country.alpha2Code}>
              {country.name}
              {
                <button onClick={() => setSelectedCountry(country)}>
                  show
                </button>
              }
            </p>
          ))}
          <div>{renderCountryDetails()}</div>
        </div>
      );
    }
    if (filteredCountries.length === 1) {
      return filteredCountries.map((country) => (
        <p key={country.alpha2Code}>
          Capital: {country.capital}. Population: {country.population}{" "}
          <img src={country.flag} />
        </p>
      ));
    }
  };
  const searchHandler = (e) => {
    setSelectedCountry("");
    setSearchFilter(e.target.value);
  };

  return (
    <div>
      <div>
        <h1>Countries</h1>
      </div>
      <div>
        Type to find countries:
        <input onChange={searchHandler} />
        <div>{showCountries()}</div>
      </div>
    </div>
  );
};

export default App;

Codesandbox – https://codesandbox.io/s/kind-bohr-2crws?file=/src/App.js

We are here to answer your question about Filter array data and return it - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji