【问题标题】:Using UseEffect Hook to Fetch API使用 UseEffect Hook 获取 API
【发布时间】:2021-03-11 06:10:51
【问题描述】:

我正在尝试通过使用提取的信息更新我的状态来从 api 获取加密货币数据。但是当我这样做时,我的 console.log 显示一个空对象。也没有数据传递给我的子组件。我在这里做错了吗?

import React, {useState, useEffect} from 'react';
import SmallBox from './SmallBox';
import './App.css';

function App() {
  const [smallData, setSmallData] = useState({})

  async function getAPI(){
    await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false
    `)
    .then(response => response.json())
    .then(data => setSmallData({data})); 
  }

  useEffect( () => {
    getAPI();
    console.log(smallData)
  }, []);


  return (
    <div className="app">
      
      {/* SmallBox - balance */}
      <SmallBox className="balance"/>
      
      {/* SmallBox - bitcoin */}
      <SmallBox className="bitcoin" coin={smallData}/>
      
      {/* SmallBox - ethereum */}
      <SmallBox className="ethereum" coin={smallData}/>
      
      {/* SmallBox - ripple */}
      <SmallBox className="ripple" coin={smallData}/>
      
      {/* SmallBox - tether */}
      <SmallBox className="tether" coin={smallData}/>
     
    </div>
  );
}

export default App;

【问题讨论】:

  • getAPI 是一个 async 函数。当您调用console.log 时,状态尚未更新。
  • 您的 API 调用和响应状态更改都是异步的,您可以在下一行打印状态值并查看更新

标签: reactjs api react-hooks jsx


【解决方案1】:

试试这个:

async function getAPI(){
    const rawData = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false`)
    const jsonData = rawData.json();
    setSmallData( state => ({...jsonData}) );
  }

useEffect(() => {
    getAPI().then(() => console.log(smallData));
  }, []);

【讨论】:

    【解决方案2】:

    在记录数据之前尝试awaiting 获取要获取的数据,而不是在async 函数getAPI 中等待获取:

      function getAPI(){
        return fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false
        `)
          .then(response => response.json())
          .then(data => setSmallData({data})); 
      }
    
      useEffect( () => {
        await getAPI();
        console.log(smallData)
      }, []); // <- Add dependencies here
    

    注意:我认为 getAPI 将在组件的每个渲染中被调用,我认为这不是你想要的。我建议为传递给useEffect 函数的第二个变量(一个空数组)添加一些依赖项,告诉 React 只有在那个/那些变量发生变化时才调用这个效果。例如,您可以添加货币。

    【讨论】:

      【解决方案3】:

      更改 useEffect 等待 getApi 函数完成。

        useEffect(() => {
          getAPI().then((_) => {
            console.log(smallData);
          });
        }, []);
      

      【讨论】:

        【解决方案4】:

        首先,您的console.log 应该显示{},因为这是smallData 的初始状态,getAPI 将异步执行。这没有什么不妥。

        但是由于您没有将数据传递给子组件的问题,可能是因为您将 smallData 设置为 { data: *api response* },也许您希望 smallData 成为 api 响应,而不是带有data 属性。

        我建议将 console.log(smallData) 放在 return 语句之前,以便在每次渲染中查看其内容。

        如果还是遇到问题,添加SmallBox组件代码,可能问题就出在这里

        【讨论】:

          【解决方案5】:

          您的 React 设置状态挂钩是异步调用的。因此,您的 smallData 将显示之前的状态,因为组件尚未重新渲染。

          你没有做错任何事。请参阅下面的注释代码以了解发生了什么。

            useEffect( () => {
              getAPI(); // 1. This call seems to be correct, and queues up setSmallData. 
              // 2. The state update has not happened yet, but the setSmallData call is queued up. 
              console.log(smallData) // 3. still {} because the state has not been updated yet, and thus is still showing the current state. 
          
            }, []);
          

          换句话说,console.log(smallData) 在你的 setSmallData 之前运行,这就是你看到一个空对象的原因(因为{} 是你的初始状态)。但是,如果您在页面的某处显示数据,您会注意到组件会随数据一起重新呈现。

          你可以试试:

              async function getAPI(){
                return await fetch(`...`)
                .then(response => response.json())
                .then(data => data); 
              }
              useEffect( () => {
               async function getApiAndSetState() {
               let data = await getAPI(); // the code pauses here until getAPI() completes.
               console.log(data); // this data is now available
               setSmallData(data);
               }
             }, []);
          

          【讨论】:

            猜你喜欢
            • 2019-10-06
            • 2019-10-15
            • 2020-01-06
            • 2020-02-02
            • 2022-01-15
            • 2021-08-02
            • 2021-04-17
            • 2019-10-08
            • 2019-11-24
            相关资源
            最近更新 更多