Reputation: 103
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;
Upvotes: 0
Views: 84
Reputation: 118
You just need pass the country variable as a argument in button click same as below.
{<button onClick={() => handleClick(country)}>show</button>}
you also need to filter the country array in button click and need to set filtered array in state so that it will update and display.
I have updated your code hereUpdated Code.
Upvotes: 1
Reputation: 6736
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
Upvotes: 1