在 Reactjs 中出现错误。它说未处理的拒绝(TypeError)。但我已经告诉它如果用户在输入中输入无效名称该怎么办

Getting an error in Reactjs. It says Unhandled Rejection (TypeError). But I already told it what to do if user types invalid name in input

只是想知道我是否可以得到 Unhandled Rejection (TypeError)。我已经放置了一个 if else 语句,告诉它呈现一个或另一个。结果,或提示输入有效国家/地区的消息。我已经在网上看了一段时间。请告诉我。谢谢。这是我的代码和错误图片。

import React, { Component } from 'react';
import './App.css';
import NavBar from "./navbar";
import axios from "axios";
import Accordion from './accordion';
import Accordions from './accordion';
import ErrorBoundary from "./Carousel";


class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      flag: undefined,
      name: undefined,
      nativeName:undefined,
      callingCodes: undefined,
      capital: undefined, 
      currencies:undefined,
      languages: undefined,
      region:undefined,
      population:undefined,
      alpha3Code:undefined,
      isSearched: false,
      subregion: undefined,
      error: ""
    }
  }


  getCity = async(e) => {
    e.preventDefault();
    const city = e.target.elements.cityname.value;
    const api_call = await fetch(`https://restcountries.eu/rest/v2/name/${city}?fullText=true`);
    const data = await api_call.json();
    console.log(data);
    this.setState({
      flag: data[0].flag,
      name: data[0].name,
      nativeName: data[0].nativeName,
      alpha3Code: data[0].alpha3Code,
      callingCodes: data[0].callingCodes,
      capital: data[0].capital,
      currencies: data[0].currencies[0].name,
      languages: data[0].languages[0].name,
      region: data[0].region,
      population: data[0].population,
      subregion:data[0].subregion
    });
}

toggleSearch = () => {
  this.setState({
    isSearched: true
  })
}



  render() {
    let search;
    if(this.state.isSearched) {
      search = 
      <div className="content-1">
      <div className="marginbottom">
        <img className="flags" src={this.state.flag}/>
          <h2><span className="bold">Name:</span> {this.state.name}</h2>
          <div><span className="bold">Native Name:</span> {this.state.nativeName}</div>
          <div><span className="bold">Abbreviation:</span> {this.state.alpha3Code}</div>
          <div><span className="bold">Calling Code:</span> {this.state.callingCodes}</div>
          <div><span className="bold">Capital: </span>{this.state.capital}</div>
          <div><span className="bold">Currencies:</span> {this.state.currencies}</div>
          <div><span className="bold">Language:</span> {this.state.languages}</div>
          <div><span className="bold">Region: </span>{this.state.region}</div>
          <div><span className="bold">Population:</span> {this.state.population}</div>
        </div>
        <Accordions name={this.state.name} population={this.state.population} subregion={this.state.subregion}/>
      </div>
    } else {
      search=<p>Enter a valid country name</p>;
    }

    return (
      <div className="App">
        <header className="App-header">
          <h1>Globe Search</h1>
          <h5>Search For Cities Around the Globe</h5>
        </header>
      <div class="content">
      <NavBar/>
      <form
         onSubmit={this.getCity}   >
            <input
               placeholder="Enter Country"
               type="text"
               name="cityname"/>
            <button onClick={this.toggleSearch} className="btn btn-success m-2">Search</button>
          </form>
          <div>
        <div>{search}</div>
        </div>  
      </div>
      </div>
    );
  }
}

export default App;

首先,您需要将按钮更改为提交类型 <button type="submit" ...>,以便调用 this.getCity。如果您需要 isSearched,请从 this.getCity 调用它或创建一个新的提交函数 handleSearch() 并将 this.toggleSearch()this.getCity() 放入其中。

import React, { Component } from 'react';
import './App.css';
import NavBar from "./navbar";
import axios from "axios";
import Accordion from './accordion';
import Accordions from './accordion';
import ErrorBoundary from "./Carousel";


class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      flag: undefined,
      name: undefined,
      nativeName:undefined,
      callingCodes: undefined,
      capital: undefined, 
      currencies:undefined,
      languages: undefined,
      region:undefined,
      population:undefined,
      alpha3Code:undefined,
      isSearched: false,
      subregion: undefined,
      error: ""
    }
  }


  getCity = async(e) => {
    e.preventDefault();

    // Call toggleSearch somewhere in here if you really need it
    this.toggleSearch();

    const city = e.target.elements.cityname.value;
    const api_call = await fetch(`https://restcountries.eu/rest/v2/name/${city}?fullText=true`);
    const data = await api_call.json();
    console.log(data);
    this.setState({
      flag: data[0].flag,
      name: data[0].name,
      nativeName: data[0].nativeName,
      alpha3Code: data[0].alpha3Code,
      callingCodes: data[0].callingCodes,
      capital: data[0].capital,
      currencies: data[0].currencies[0].name,
      languages: data[0].languages[0].name,
      region: data[0].region,
      population: data[0].population,
      subregion:data[0].subregion
    });
}

toggleSearch = () => {
  this.setState({
    isSearched: true
  })
}



  render() {
    let search;
    if(this.state.isSearched) {
      search = 
      <div className="content-1">
      <div className="marginbottom">
        <img className="flags" src={this.state.flag}/>
          <h2><span className="bold">Name:</span> {this.state.name}</h2>
          <div><span className="bold">Native Name:</span> {this.state.nativeName}</div>
          <div><span className="bold">Abbreviation:</span> {this.state.alpha3Code}</div>
          <div><span className="bold">Calling Code:</span> {this.state.callingCodes}</div>
          <div><span className="bold">Capital: </span>{this.state.capital}</div>
          <div><span className="bold">Currencies:</span> {this.state.currencies}</div>
          <div><span className="bold">Language:</span> {this.state.languages}</div>
          <div><span className="bold">Region: </span>{this.state.region}</div>
          <div><span className="bold">Population:</span> {this.state.population}</div>
        </div>
        <Accordions name={this.state.name} population={this.state.population} subregion={this.state.subregion}/>
      </div>
    } else {
      search=<p>Enter a valid country name</p>;
    }

    return (
      <div className="App">
        <header className="App-header">
          <h1>Globe Search</h1>
          <h5>Search For Cities Around the Globe</h5>
        </header>
      <div class="content">
      <NavBar/>
      <form
         onSubmit={this.getCity}   >
            <input
               placeholder="Enter Country"
               type="text"
               name="cityname"/>

            {/* Removed onClick and added type="submit" */}
            <button type="submit" className="btn btn-success m-2">Search</button>

          </form>
          <div>
        <div>{search}</div>
        </div>  
      </div>
      </div>
    );
  }
}

export default App;

看起来像这条线

const city = e.target.elements.cityname.value;

没有收到预期值。结果,您在此处获取未知 url:

const api_call = await fetch(`https://restcountries.eu/rest/v2/name/${city}?fullText=true`);

那么下面的所有内容都是未定义的,你会收到这样的错误。

当您提交空值或无效位置时,您将收到错误消息,因为您将尝试获取未知 url。因此您可以检查城市值是否为空,还可以检查 api 的响应并相应地更新状态

 getCity = async(e) => {
    e.preventDefault();
    const city = e.target.elements.cityname.value;
    // check if input field is empty or not
    if(city) {
      const api_call = await fetch(`https://restcountries.eu/rest/v2/name/${city}?fullText=true`);
      const data = await api_call.json();
      console.log(data);
      // check if value entered in input is valid 
      // so check api returns a valid response or not
      if(data && !data.status) {
        this.setState({
        isSearched: true,
        flag: data[0].flag,
        name: data[0].name,
        nativeName: data[0].nativeName,
        alpha3Code: data[0].alpha3Code,
        callingCodes: data[0].callingCodes,
        capital: data[0].capital,
        currencies: data[0].currencies[0].name,
        languages: data[0].languages[0].name,
        region: data[0].region,
        population: data[0].population,
        subregion:data[0].subregion
       });
      } else {
        this.setState({
          isSearched:false
        })
      }   
    } else {
      this.setState({
        isSearched:false
      })
    }    
  }

并将按钮更改为 type="submit"

<button type="submit" className="btn btn-success m-2">Search</button>

不需要toggleSearch方法

一切都会好的

import React, { Component } from 'react';
import './App.css';

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      flag: undefined,
      name: undefined,
      nativeName:undefined,
      callingCodes: undefined,
      capital: undefined, 
      currencies:undefined,
      languages: undefined,
      region:undefined,
      population:undefined,
      alpha3Code:undefined,
      isSearched: false,
      subregion: undefined,
      error: ""
    }
  }


  getCity = async(e) => {
    e.preventDefault();
    const city = e.target.elements.cityname.value;
    const api_call = await fetch(`https://restcountries.eu/rest/v2/name/${city}?fullText=true`);
    api_call.json()
    .then((data) => {
      this.setState({
        flag: data[0].flag,
        name: data[0].name,
        nativeName: data[0].nativeName,
        alpha3Code: data[0].alpha3Code,
        callingCodes: data[0].callingCodes,
        capital: data[0].capital,
        currencies: data[0].currencies[0].name,
        languages: data[0].languages[0].name,
        region: data[0].region,
        population: data[0].population,
        subregion:data[0].subregion,
        error: ''
      });
    })
    .catch((error) => {
      this.setState({error})
    })
}

toggleSearch = () => {
  this.setState({
    isSearched: true
  })
}



  render() {
    let search;
    if(this.state.isSearched && this.state.error === '') {
      search = 
      <div className="content-1">
      <div className="marginbottom">
        <img className="flags" src={this.state.flag}/>
          <h2><span className="bold">Name:</span> {this.state.name}</h2>
          <div><span className="bold">Native Name:</span> {this.state.nativeName}</div>
          <div><span className="bold">Abbreviation:</span> {this.state.alpha3Code}</div>
          <div><span className="bold">Calling Code:</span> {this.state.callingCodes}</div>
          <div><span className="bold">Capital: </span>{this.state.capital}</div>
          <div><span className="bold">Currencies:</span> {this.state.currencies}</div>
          <div><span className="bold">Language:</span> {this.state.languages}</div>
          <div><span className="bold">Region: </span>{this.state.region}</div>
          <div><span className="bold">Population:</span> {this.state.population}</div>
        </div>
      </div>
    } else {
      search=<p>Enter a valid country name</p>;
    }

    return (
      <div className="App">
        <header className="App-header">
          <h1>Globe Search</h1>
          <h5>Search For Cities Around the Globe</h5>
        </header>
      <div class="content">
      <form
         onSubmit={this.getCity}   >
            <input
               placeholder="Enter Country"
               type="text"
               name="cityname"/>
            <button onClick={this.toggleSearch} className="btn btn-success m-2">Search</button>
          </form>
          <div>
        <div>{search}</div>
        </div>  
      </div>
      </div>
    );
  }
}

export default App;