开发者问题收集

第一次使用 React 中的 API - Openweather API - TypeError: 无法读取未定义的属性“temp”

2021-02-18
340

我一直在开发一个小型仪表板应用程序,试图获取我所在城市的温度并希望将其显示出来。我还搜索了十几个有类似问题的帖子,感觉我快要解决了。

我已使用 教程作为参考。

主要问题是,当我尝试访问返回中的 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;
3个回答

有多种方法,使用 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

Learner
2021-02-18

在您的第一个渲染周期中,apiData 只是 {},因为这就是您在 setState 中初始化它的方式。这是在调用 API 之前。React 尝试渲染您的组件,但无法渲染,因为它没有数据。不要假设您在渲染组件时已经获取了数据,您应该先检查一下。因此,类似于:

return(
   apiData.main ? ...yourComponentHere : <div>...Loading</div>
)

显然,这可以通过加载微调器、处理超时等来做得更好,但这是您问题的根源。

编辑:如果您想在获取数据的同时以优雅的方式处理渲染,您可以阅读 suspense

Supperhero
2021-02-18

这是因为您的 HTML 在接收数据之前呈现, 在您的返回中将以下行

                <p>{apiData.main.temp}</p>

替换为此

                <p>{(apiData.main || {}).temp || 'loading temp...'}</p>
Sabir
2021-02-18