You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>- &deg;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>- &deg;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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 16:15:38