+-
使用React Hooks在第二次渲染时进行API调用。

我想做的是从一个天气API中获取数据,但是在第一次渲染时,"数据 "状态是空的,而在第二次渲染时,API被调用,数据被设置。这使得当我稍后试图访问图像的数据时,我得到一个错误。TypeError: Cannot read property 'weather' of undefined因为它最初是空的。不知何故,我需要跟踪渲染发生了多少次,或者改变我获取数据的方式。我想 useEffect 的第二个参数为空列表,将作为 componentDidMount. 这是我的代码。

import React, {useState, useEffect} from 'react';

export default function App() {
  const useFetch = () =>{
    const [data, setData] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect( () => {
      async function fetchData(){
      const response = await fetch('https://api.weatherbit.io/v2.0/forecast/hourly?city=Chicago,IL&key=XXX&hours=24');
      const json = await response.json();
      setData(json.data);
      setLoading(false);
      }
      fetchData();
    }, []);
    return {data, loading};
  }

  const convert = (c) =>{
    let f = (c*(9/5))+32;
    return f
   }


  const {data, loading} = useFetch();
  console.log(data)
  return (
    <div>
      <img src={'https://www.weatherbit.io/static/img/icons/'+data[0].weather.icon+'.png'}/>
      <h1>{loading ? 'Loading...' : ''}</h1>
    </div>
  )
}


2
投票

传递给 useEffect 将在渲染提交到屏幕后运行,默认情况下,特效在每次完成渲染后运行。您需要在每次渲染完成后渲染 img 只有当api调用完成时,即当加载完成时 false.

import React, {useState, useEffect} from 'react';

export default function App() {
  const useFetch = () =>{
    const [data, setData] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect( () => {
      async function fetchData(){
      const response = await fetch('https://api.weatherbit.io/v2.0/forecast/hourly?city=Chicago,IL&key=XXX&hours=24');
      const json = await response.json();
      setData(json.data);
      setLoading(false);
      }
      fetchData();
    }, []);
    return {data, loading};
  }

  const convert = (c) =>{
    let f = (c*(9/5))+32;
    return f
   }


  const {data, loading} = useFetch();

  if(loading) {
     return <h1>{'Loading...'}</h1>
  }

  return (
    <div>
      <img src = {'https://www.weatherbit.io/static/img/icons/'+data[0].weather.icon+'.png'}/>
    </div>
  )
}
0
投票

你可以试试这样

const [data, setData] = useState(null);

return (
   {data ? ( <div>
     <img src={'https://www.weatherbit.io/static/img/icons/'+data[0].weather.icon+'.png'}/>
     <h1>{loading ? 'Loading...' : ''}</h1>
   </div>) : <p>Loading....<p>}
 )

这在第一次渲染时将数据设置为null,渲染函数中的条件渲染会检查数据是否为真或是否有数据,如果没有则返回加载... 文本

0
投票

你可以在渲染函数中加入一个条件。

  return (
    <div>
      {data && data.weather && <img src={'https://www.weatherbit.io/static/img/icons/'+data[0].weather.icon+'.png'}/>}
      <h1>{loading ? 'Loading...' : ''}</h1>
    </div>
  )