Reputation: 256
I managed to fetch data from API. Now I want to get a specific data from search input without click.I guess I need here filter function. I managed to listen to input from clicking. But how to get data?
Any help will be appreciated.
Here is my code
import React, { useState, useEffect } from "react";
import CountryListCard from "./CountryListCard";
import "./CountryList.scss";
export default function CountryList() {
const [data, setData] = useState([]);
const [search, setSearch] = useState("");
const fetchData = () => {
fetch("https://restcountries.eu/rest/v2/all")
.then((res) => res.json())
.then((result) => setData(result))
.catch((err) => console.log("error"));
};
useEffect(() => {
fetchData();
}, []);
function handleChange(e) {
console.log(e.target.value);
}
return (
<div>
<input
className="input"
type="text"
placeholder="search country ..."
value={search}
onChange={handleChange}
/>
{data &&
data.map((country) => (
<div className="CountryList" key={country.name}>
<div className="CountryListImg">
<img src={country.flag} alt="" width="80px" />
</div>
<div className="countryName">{country.name}</div>
<div className="population">{country.population}</div>
<div className="region">{country.region}</div>
<div>
{country.languages.map((language, languageIndex) => (
<div key={languageIndex}>{language.name}</div>
))}
</div>
</div>
))}
</div>
);
}
Upvotes: 1
Views: 3143
Reputation: 2104
First, install lodash if you don't have
npm install lodash
And use debounce
// Lodash here <<<<<<<<<<<<<<<<
import { debounce } from 'lodash';
export default function CountryList() {
const [data, setData] = useState([]);
const [search, setSearch] = useState("");
const fetchData = (text) => {
// Fix your API with text search here <<<<<<<<<<<<<<,
fetch("https://restcountries.eu/rest/v2/all")
.then((res) => res.json())
.then((result) => setData(result))
.catch((err) => console.log("error"));
};
useEffect(() => {
fetchData();
}, []);
function handleChange(e) {
setSearch(e)
onSearch(e)
console.log(e.target.value);
}
const onSearch = debounce((text) => {
fetchData(text);
}, 500)
return (
<div>
<input
className="input"
type="text"
placeholder="search country ..."
value={search}
onChange={handleChange}
/>
{data &&
data.map((country) => (
<div className="CountryList" key={country.name}>
<div className="CountryListImg">
<img src={country.flag} alt="" width="80px" />
</div>
<div className="countryName">{country.name}</div>
<div className="population">{country.population}</div>
<div className="region">{country.region}</div>
<div>
{country.languages.map((language, languageIndex) => (
<div key={languageIndex}>{language.name}</div>
))}
</div>
</div>
))}
</div>
);
}
Upvotes: 0
Reputation: 202706
You can filter in-line when rendering the data. Remember to do case-insensitive string comparisons
data
.filter(
(country) =>
!search || country.name.toLowerCase().includes(search.toLowerCase())
)
.map(country => ...)
If the search is falsey, i.e. ""
the filter returns true and country is returned, otherwise the country's name is checked if it includes the search value.
To save the input value
function handleChange(e) {
const { value } = e.target;
setSearch(value);
}
Upvotes: 1
Reputation: 1297
useEffect(() => {
const fetchData = () => {
fetch("https://restcountries.eu/rest/v2/all")
.then((res) => res.json())
.then((result) => setData(result))
.catch((err) => console.log("error"));
};
fetchData();
}, []);
function handleChange(e) {
setSearch(e.target.value)
}
return (
<div>
<input
className="input"
type="text"
placeholder="search country ..."
value={search}
onChange={handleChange}
/>
{data &&
data.filter(item=> item.name.includes(search)).map((country) => (
<div className="CountryList" key={country.name}>
<div className="CountryListImg">
<img src={country.flag} alt="" width="80px" />
</div>
<div className="countryName">{country.name}</div>
<div className="population">{country.population}</div>
<div className="region">{country.region}</div>
<div>
{country.languages.map((language, languageIndex) => (
<div key={languageIndex}>{language.name}</div>
))}
</div>
</div>
))}
</div>
);
Upvotes: 2