首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尝试使用useEffect钩子从api获取数据时,应作出错误反应

尝试使用useEffect钩子从api获取数据时,应作出错误反应
EN

Stack Overflow用户
提问于 2022-04-04 06:48:38
回答 5查看 122关注 0票数 0

我试图创建一个简单的天气网络应用程序使用一个api,其中包含一个输入表单,以搜索城市和信息显示。我希望使用useEffect挂钩将默认城市设置为特定城市。因此,一旦用户打开应用程序,有关城市天气的信息就会显示出来。但是,它返回一个错误,表明数据不存在。

这是我的App.js文件

代码语言:javascript
复制
import React, { useState, useEffect } from 'react'
import Search from './components/Search.js'
import './App.scss';

function App() {
  const [city, setCity] = useState('London')
  const [unit, setUnit] = useState('metric')
  const [info, setInfo] = useState({})

  const key = process.env.REACT_APP_WEATHER_API_KEY
  const api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}&units=${unit}`

  useEffect(() => {
    fetch(api)
      .then(res => {
        if (!res.ok){
          throw Error('could not fetch the data')
        } 
        return res.json()
      })
      .then(data => {
        setInfo(data)
        console.log(data)
      })
      .catch(err => console.log(err.message))
  }, [city])  


  return (
    <div className="app">
      <Search setCity={setCity}/> 

      <h1 className='city'>{city}</h1>
      <h2 className='temperature'>Temperature: {info.main.temp}</h2>
    </div>
  );
}

export default App;

Search.js文件

代码语言:javascript
复制
import React from 'react'

function Search({setCity}) {

  const search = (e) => {
    const loc = e.target.value.trim().replace(/^\w/, (c) => c.toUpperCase())
    if (e.key === 'Enter' && loc !== ''){
      setCity(loc)
    }
  }

  return (
    <div className='search-container'>
      <input type="text" onKeyPress={search} defaultValue='London'/>
    </div>
  )
}

export default Search

错误消息

代码语言:javascript
复制
Uncaught TypeError: Cannot read properties of undefined (reading 'temp')

似乎发生了错误,因为我试图访问h2标记中的温度信息(H2)。但是,如果我删除它,一切都将正常工作,并且信息仍将从api中检索。

EN

回答 5

Stack Overflow用户

发布于 2022-04-04 07:02:30

你已经将info初始化为一个空对象-

代码语言:javascript
复制
const [info, setInfo] = useState({})

当您的组件第一次呈现时,info对象上没有info属性(因为它是空的),因此此调用将始终失败,出现您正在看到的错误:

代码语言:javascript
复制
<h2 className='temperature'>Temperature: {info.main.temp}</h2>

要修复它,可以在使用可选链访问该属性之前检查该属性是否存在。

代码语言:javascript
复制
<h2 className='temperature'>Temperature: {info.main?.temp}</h2>
票数 0
EN

Stack Overflow用户

发布于 2022-04-04 07:04:34

你的useEffect依赖于“城市”。在开始时,您试图在任何城市变化之前显示温度值。

要解决这个问题,您可以避免试图显示标记:

代码语言:javascript
复制
{info && <h2 className='temperature'>Temperature: {info.main.temp}</h2>}

或者:

代码语言:javascript
复制
{info ? <h2 className='temperature'>Temperature: {info.main.temp}</h2> : <Loading/>}

在这种情况下,不需要将默认值设置为"info“useState。

代码语言:javascript
复制
const [info, setInfo] = useState()
票数 0
EN

Stack Overflow用户

发布于 2022-04-04 07:06:41

如果您检查info.main不是未定义的,然后呈现出来,那就更好了。

代码语言:javascript
复制
import React, { useState, useEffect } from 'react'
import Search from './components/Search.js'
import './App.scss';

function App() {
  const [city, setCity] = useState('London')
  const [unit, setUnit] = useState('metric')
  const [info, setInfo] = useState({})

  const key = process.env.REACT_APP_WEATHER_API_KEY
  const api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}&units=${unit}`

  useEffect(() => {
    fetch(api)
      .then(res => {
        if (!res.ok){
          throw Error('could not fetch the data')
        } 
        return res.json()
      })
      .then(data => {
        setInfo(data)
        console.log(data)
      })
      .catch(err => console.log(err.message))
  }, [city])  


  return (
    <div className="app">
      <Search setCity={setCity}/> 

      <h1 className='city'>{city}</h1>
      {info.main ? (
        <h2 className='temperature'>Temperature: {info.main.temp}</h2>
      ) : (
        <h2 className='loading'>Loading...</h2>
      )}
    </div>
  );
}

export default App;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71733044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档