【问题标题】:Make an API call on second render using React Hooks使用 React Hooks 对第二次渲染进行 API 调用
【发布时间】:2020-05-14 00:52:54
【问题描述】:

我想做的是从天气 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>
  )
}


【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    传递给useEffect 的函数将在渲染提交到屏幕后运行,默认情况下,效果会在每次完成渲染后运行。仅当 api 调用完成时,即加载为 false 时,您才需要渲染 img

    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>
      )
    }
    

    【讨论】:

      【解决方案2】:

      你可以试试这样的

      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,渲染函数中的条件渲染会检查数据是否为真/或有数据,如果没有则返回正在加载...文本

      【讨论】:

        【解决方案3】:

        你可以在渲染函数中放置一个条件

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

        【讨论】:

          猜你喜欢
          • 2020-01-15
          • 2021-09-09
          • 1970-01-01
          • 2020-02-23
          • 1970-01-01
          • 2023-04-04
          • 1970-01-01
          • 2019-04-18
          相关资源
          最近更新 更多