第一次使用 React 中的 API - Openweather API - TypeError: 无法读取未定义的属性“temp”
我一直在开发一个小型仪表板应用程序,试图获取我所在城市的温度并希望将其显示出来。我还搜索了十几个有类似问题的帖子,感觉我快要解决了。
我已使用 本 教程作为参考。
主要问题是,当我尝试访问返回中的
apiData.main.temp
时,出现“TypeError:无法读取未定义的属性‘temp’”错误。通过控制台查看,温度值似乎位于这一行内,但我似乎无法让它工作。
提前谢谢大家!我正在努力学习,希望我没有以愚蠢的方式搞砸事情,我非常高兴能够被展示正确的方法!
谢谢!
这是 App 组件的代码:
function App() {
// State
const [apiData, setApiData] = useState({});
const weatherInCity = "Vienna";
// API KEY AND URL
const apiKey = process.env.REACT_APP_API_KEY;
const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${weatherInCity}&units=metric&appid=${apiKey}`;
// Side effect
useEffect(() => {
fetch(apiUrl)
.then((res) => res.json())
.then((data) => setApiData(data));
}, [apiUrl]);
return (
<div className="App">
<div className="app-item">
<h1>Temperature</h1>
<p>{apiData.main.temp}</p>
</div>
</div>
);
}
export default App;
有多种方法,使用 useEffect 是其中一种方式
所以这里的问题是你正在调用一个异步请求,所以它的响应是在未来的等待时间内,你的渲染已经完成,apiData 为空,所以这就是你收到错误的原因,所以你需要做的是编写另一个 useEffect,将数组 deps 作为 apiData,这样当它改变时,你可以在渲染时获取该值
const [temp, setTemp] = useState(null)
useEffect(() => {
if(!apiData?.main?.temp) return
setTemp(apiData.main.temp)
}, [apiData])
在你的回报中
<p>{temp && temp}</p>
你甚至可以添加三元检查并显示文本加载,一旦加载 api 成功,你就可以访问 apiData?.main?.temp
在您的第一个渲染周期中,apiData 只是 {},因为这就是您在 setState 中初始化它的方式。这是在调用 API 之前。React 尝试渲染您的组件,但无法渲染,因为它没有数据。不要假设您在渲染组件时已经获取了数据,您应该先检查一下。因此,类似于:
return(
apiData.main ? ...yourComponentHere : <div>...Loading</div>
)
显然,这可以通过加载微调器、处理超时等来做得更好,但这是您问题的根源。
编辑:如果您想在获取数据的同时以优雅的方式处理渲染,您可以阅读 suspense 。
这是因为您的 HTML 在接收数据之前呈现, 在您的返回中将以下行
<p>{apiData.main.temp}</p>
替换为此
<p>{(apiData.main || {}).temp || 'loading temp...'}</p>