You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 01:54:07