React类组件误用Hooks报错:Invalid hook call问题求助
解决React中"Invalid hook call"错误并实现天气API调用
错误原因
你遇到的报错是因为React Hooks(如useState、useEffect)只能在函数组件的顶层作用域内使用,但你把useState写在了类组件Counter的外部,完全违反了Hook的使用规则。此外代码还有几处问题:未定义Halifax变量、未导入axios、本地图片用绝对路径不符合React规范等。
修复方案一:改为函数组件(推荐)
Hook是为函数组件设计的,改用函数组件更贴合React现代写法:
import React, { useEffect, useState } from "react"; import axios from "axios"; // 先执行npm install axios安装并导入 export default function Counter() { const [data, setData] = useState({}); const apiKey = "f56f24967aaf51182d1d4df628297c6d"; const targetCity = "Halifax"; const getWeatherDetails = (cityName) => { if (!cityName) return; const apiURL = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${apiKey}`; axios.get(apiURL) .then((res) => { console.log("response", res.data); setData(res.data); }) .catch((err) => { console.log("err", err); }); }; // 组件挂载时自动调用API获取天气 useEffect(() => { getWeatherDetails(targetCity); }, []); return ( <div> <br /> <br /> {/* 建议将图片放入项目public文件夹,改用相对路径:<img src="/Capture.PNG" alt="Surat city" /> */} <img src="E:\MCDA\vs react\Project1\Project1\Capture.PNG" alt="Surat city" /><br /> <br /> <h2><b>I live in Surat.</b></h2><br /> <br /> <p>Surat is a city located in Gujarat in India. It is also known as Diamond hub. Surat is also know for its textile market.</p> <br /> <br /> {/* 同样建议改用public文件夹相对路径 */} <img src="E:\MCDA\vs react\Project1\Project1\weather.png" alt="Weather icon" /><br /> <p>- °C</p> <h6 className="weatherTemp"> {data?.main?.temp ? ((data.main.temp - 273.15).toFixed(2)) : "Loading..."}°C </h6> </div> ); }
修复方案二:保留类组件,用生命周期替代Hook
如果坚持使用类组件,需将状态移入类的state,用componentDidMount替代useEffect调用API:
import React, { Component } from 'react'; import axios from "axios"; // 导入axios export class Counter extends Component { static displayName = Counter.name; constructor(props) { super(props); this.state = { currentCount: 0, data: {} // 将天气数据存入类的state }; this.incrementCounter = this.incrementCounter.bind(this); this.getWeatherDetails = this.getWeatherDetails.bind(this); } incrementCounter() { this.setState({ currentCount: this.state.currentCount + 1 }); } getWeatherDetails(cityName) { if (!cityName) return; const apiKey = "f56f24967aaf51182d1d4df628297c6d"; const apiURL = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${apiKey}`; axios.get(apiURL) .then((res) => { console.log("response", res.data); this.setState({ data: res.data }); // 更新类的state }) .catch((err) => { console.log("err", err); }); } // 组件挂载完成后调用API componentDidMount() { this.getWeatherDetails("Halifax"); } render() { const { data } = this.state; return ( <div> <br /> <br /> <img src="E:\MCDA\vs react\Project1\Project1\Capture.PNG" alt="Surat city" /><br /> <br /> <h2><b>I live in Surat.</b></h2><br /> <br /> <p>Surat is a city located in Gujarat in India. It is also known as Diamond hub. Surat is also know for its textile market.</p> <br /> <br /> <img src="E:\MCDA\vs react\Project1\Project1\weather.png" alt="Weather icon" /><br /> <p>- °C</p> <h6 className="weatherTemp"> {data?.main?.temp ? ((data.main.temp - 273.15).toFixed(2)) : "Loading..."}°C </h6> </div> ); } }
额外注意事项
- 必须安装axios:在项目根目录执行
npm install axios - 本地图片路径:React项目建议将图片放入
public文件夹,用相对路径引用,绝对路径在打包后可能失效 - 加载状态处理:添加
Loading...提示,避免数据未返回时显示NaN
内容的提问来源于stack exchange,提问作者shital
相关产品推荐
相关产品推荐

