获取api时未调用useEffect且未更新状态

Nav*_*aur 5 javascript reactjs react-hooks use-effect

我正在使用 useEffect 钩子从天气 api 获取数据并正确声明依赖项。我的状态仍未更新,因此我的渲染函数出现错误。我几乎尝试了从摆脱依赖数组到在依赖数组中声明倍数的所有方法。我不知道我的功能有什么问题。API 的 JSON 响应格式如下:

{
 location: {
 name: "Paris",
 region: "Ile-de-France",
 },
 current: {
  last_updated_epoch: 1564279222,
  last_updated: "2019-07-28 04:00",
  temp_c: 16,
  temp_f: 60.8,
  is_day: 0,
  condition: {
    text: "Clear",
    icon: "//cdn.apixu.com/weather/64x64/night/113.png",
    code: 1000
  },
  wind_mph: 6.9,
  wind_kph: 11.2
 }
}
Run Code Online (Sandbox Code Playgroud)

这就是我的代码的样子:

const Weather = ({ capital }) => {
  const [weather, setWeather] = useState(null);

  useEffect(() => {
    console.log("useEffect called");
    const getWeather = async () => {
      try {
        const res = await axios.get(
          `http://api.apixu.com/v1/current.json?key=53d601eb03d1412c9c004840192807&q=${capital}`
        );
        setWeather(res.data);
      } catch (e) {
        console.log(e);
      }
    };
    getWeather();
  }, [capital]);
  console.log(weather);

  return (
    <Card style={{ width: "18rem", marginTop: "25px" }}>
      <Card.Img variant="top" src={weather.current.condition.icon} />

      <Card.Header style={{ textAlign: "center", fontSize: "25px" }}>
        Weather in {capital}
      </Card.Header>
    </Card>
  )
}
Run Code Online (Sandbox Code Playgroud)

我希望能够看到图标的图像,但我在渲染函数中收到此错误消息:

TypeError: Cannot read property 'current' of null
Weather
src/components/Weather.js:26
  23 | 
  24 | return (
  25 |   <Card style={{ width: "18rem", marginTop: "25px" }}>
  26 |     <Card.Img variant="top" src={weather.current.condition.icon} />
     | ^  27 | 
  28 |     <Card.Header style={{ textAlign: "center", fontSize: "25px" }}>
  29 |       Weather in {capital}
Run Code Online (Sandbox Code Playgroud)

并且我console.log(weather)返回 null,原始状态,即使它在 useEffect() 之后被调用并且console.log(useEffect called)根本不记录,这意味着 useEffect 没有被调用。

Moe*_*Moe 15

错误信息给出去了,Cannot read property 'current' of null只住的地方current被称为是weather.currentsrcCard.Img,所以我们推断,weathernull在呈现。

发生这种情况的原因是因为 api 调用是异步的,它不会立即填充状态,所以渲染首先发生并尝试.current从初始天气状态读取null

解决方案:在你的render方法中,确保不要读取weather.currentwhile weatheris null

例如,您可以使用{weather && <Card>...</Card}隐藏整个卡片直到数据加载并显示加载指示器,或者您可以将其src={weather && weather.current.condition.icon}用作快速解决方法。

const Weather = ({capital}) => {
  const [weather, setWeather] = useState(null);

  useEffect(() => {
    console.log("useEffect called");
    const getWeather = async () => {
      try {
        const res = await axios.get(
          `http://api.apixu.com/v1/current.json?key=53d601eb03d1412c9c004840192807&q=${capital}`,
        );
        setWeather(res.data);
      } catch (e) {
        console.log(e);
      }
    };
    getWeather();
  }, [capital]);
  console.log(weather);

  return (
    <Card style={{width: "18rem", marginTop: "25px"}}>
      <Card.Img variant="top" src={weather && weather.current.condition.icon} />

      <Card.Header style={{textAlign: "center", fontSize: "25px"}}>
        Weather in {capital}
      </Card.Header>
    </Card>
  );
};
Run Code Online (Sandbox Code Playgroud)

  • 发生这种情况的原因是因为 api 调用是异步的,它不会立即填充状态,因此渲染首先发生并尝试从初始状态“null”读取“.current” (2认同)