React点击Show按钮展示国家详情报toLowerCase不是函数如何解决
错误原因
你遇到的newSearch.toLowerCase is not a function报错核心原因是类型不匹配:
- 你的
newSearch状态原本是存储搜索关键词的字符串类型 - 点击按钮时你把
Array.filter返回的数组赋值给了newSearch,数组没有toLowerCase方法,所以调用时直接抛出异常 - 同时你的按钮没有绑定对应的国家信息,点击时无法识别要展示哪个国家的详情
修复步骤
1. 修改Countries组件的按钮调用逻辑
在渲染Show按钮时,把当前国家的名称传递给Button组件
// Countries组件else分支修改后 else { return ( <ul> {countries.map((country, i) => ( <li key={i}> {country.name} {/* 传递当前国家名称给Button组件 */} <Button handleViewButton={handleViewButton} countryName={country.name} /> </li> ))} </ul> ) };
2. 修改Button组件的点击逻辑
接收国家名称参数,点击时传递给父组件的处理函数
const Button = ({handleViewButton, countryName}) => { return ( <button onClick={() => handleViewButton(countryName)}>Show</button> ); };
3. 修复App组件的handleViewButton函数
直接把点击的国家名称赋值给newSearch,保持其字符串类型,触发过滤后只会剩下对应的单个国家,自动触发详情渲染
const handleViewButton = (countryName) => { // 直接赋值国家名称,保持newSearch为字符串类型 setNewSearch(countryName); };
完整修改后代码
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; if (countriesLen === 0) { return ( <p>Please try another search...</p> ); } else if (countriesLen === 1) { return ( <ul> {countries.map((country, i) => <Country key={i} 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} countryName={country.name} /> </li> ))} </ul> ) }; }; const Button = ({handleViewButton, countryName}) => { return ( <button onClick={() => handleViewButton(countryName)}>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 = (countryName) => { setNewSearch(countryName); }; const showCountrySearch = newSearch ? countries.filter(country => country.name.toLowerCase().includes(newSearch.toLowerCase())) : countries; useEffect(() => { axios .get('https://restcountries.com/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;
注:代码中已将旧的restcountries接口域名更新为当前可用的版本,避免接口请求失败。
内容的提问来源于stack exchange,提问作者JackJack
相关产品推荐
相关产品推荐

