我正在从 Restcountries API 中提取国家/地区,如果数组的当前状态有超过一个或少于或等于 10 个国家/地区,我想列出国家/地区名称以及每个国家/地区旁边的“显示”按钮一。显示按钮应该显示我的 Country
函数的返回(渲染)中的内容。在 App
函数中,我为名为 handleViewButton
的按钮编写了一个处理程序。我对如何在 Countries
条件语句中过滤 else
函数中的元素以显示 Country
感到困惑。我尝试将 handleViewButton
传递给 Button
函数,但出现错误“Uncaught TypeError: newSearch.toLowerCase is not a function”。我真的只想触发 Country
函数来显示按下的国家/地区按钮。
App.js
import React, { useState, useEffect } from 'react';
import './App.css';
import axios from 'axios';
const Country = ({country}) => {
return (
<>
<h2>{country.name}</h2>
<p>capital {country.capital}</p>
<p>population {country.population}</p>
<br/>
<h3>languages</h3>
{country.languages.map(language => <li key={language.name}>{language.name}</li>)}
<br/>
<img src={country.flag} alt="country flag" style={{ width: '250px'}}/>
</>
);
}
const Countries = ({countries, handleViewButton}) => {
const countriesLen = countries.length;
console.log(countriesLen)
if (countriesLen === 0) {
return (
<p>Please try another search...</p>
);
} else if (countriesLen === 1) {
return (
<ul>
{countries.map((country, i) => <Country key={i} countriesLen={countriesLen} country={country}/>)}
</ul>
);
} else if (countriesLen > 10) {
return (
<div>
<p>Too many matches, specify another filter</p>
</div>
);
} else {
return (
<ul>
{countries.map((country, i) => <li key={i}>{country.name}<Button handleViewButton={handleViewButton}/></li>)}
</ul>
)
};
};
const Button = ({handleViewButton}) => {
return (
<button onClick={handleViewButton}>Show</button>
);
};
const Input = ({newSearch, handleSearch}) => {
return (
<div>
find countries <input value={newSearch} onChange={handleSearch}/>
</div>
);
};
function App() {
const [countries, setCountries] = useState([]);
const [newSearch, setNewSearch] = useState('');
const handleSearch = (event) => {
const search = event.target.value;
setNewSearch(search);
};
const handleViewButton = (event) => {
const search = event.target.value;
setNewSearch(countries.filter(country => country === search));
};
const showCountrySearch = newSearch
? countries.filter(country => country.name.toLowerCase().includes(newSearch.toLowerCase()))
: countries;
useEffect(() => {
axios
.get('https://restcountries.eu/rest/v2/all')
.then(res => {
setCountries(res.data);
console.log('Countries array loaded');
})
.catch(error => {
console.log('Error: ', error);
})
}, []);
return (
<div>
<Input newSearch={newSearch} handleSearch={handleSearch}/>
<Countries countries={showCountrySearch} handleViewButton={handleViewButton}/>
</div>
);
};
export default App;
答案 0 :(得分:1)
您可以使用 displayCountry
来处理应显示的国家/地区。大多数情况下,您会使用 ID,但我在这里使用 country.name
,因为它应该是唯一的。
然后您将使用 matchedCountry
查找您的国家/地区列表。
之后,使用 onHandleSelectCountry
选择给定的国家/地区。如果它已被选中,那么您可以设置为 null
以取消选中。
最后,您将有条件地呈现您的 matchedCountry
:
const Countries = ({countries}) => {
const [displayCountry, setDisplayCountry] = useState(null);
const countriesLen = countries.length;
const matchedCountry = countries.find(({ name }) => name === displayCountry);
const onHandleSelectCountry = (country) => {
setDisplayCountry(selected => {
return selected !== country.name ? country.name : null
})
}
if (countriesLen === 0) {
return (
<p>Please try another search...</p>
);
} else if (countriesLen === 1) {
return (
<ul>
{countries.map((country, i) => <Country key={i} countriesLen={countriesLen} country={country}/>)}
</ul>
);
} else if (countriesLen > 10) {
return (
<div>
<p>Too many matches, specify another filter</p>
</div>
);
} else {
return (
<>
<ul>
{countries.map((country, i) => <li key={i}>{country.name}<Button handleViewButton={() => onHandleSelectCountry(country)}/></li>)}
</ul>
{ matchedCountry && <Country countriesLen={countriesLen} country={matchedCountry}/> }
</>
)
};
};
答案 1 :(得分:0)
我只能帮助指出一些指导方针。
First:按钮没有 value 属性。因此,您从 event.target.value 得到的总是空白。
const Button = ({handleViewButton}) => {
return (
<button onClick={handleViewButton}>Show</button>
);};
First->Suggestion:给按钮添加值,当然需要传入值。
const Button = ({handleViewButton, value}) => {
return (
<button onClick={handleViewButton} value={value}>Show</button>
);};
第二:对于您的问题“未捕获的类型错误:newSearch.toLowerCase 不是函数”。 Filter 总是返回一个数组,而不是单个值。如果你使用控制台或一些沙箱 [1,2,3].filter(x=>x===2) 你会得到 [2] 而不是 2。
const handleViewButton = (event) => {
const search = event.target.value;
setNewSearch(countries.filter(country => country === search));
};
第二个->建议:更改它以获取数组中的第一个元素,因为国家(逻辑上)是唯一的。
const result = countries.filter(country => country === search)
setNewSearch(result.length>0?result[0]:"");
一个更好的数组方法是 find,它总是返回第一个结果并作为一个值。例如。 [1,2,2,3].find(x=>x===2) 你会得到 2 而不是 [2,2] 或 [2]。
countries.find(country => country === search)