reactjs 使用UseEffect钩子获取API

f45qwnt8  于 2023-02-08  发布在  React
关注(0)|答案(5)|浏览(138)

我试图从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;
kdfy810k

kdfy810k1#

在记录数据之前尝试await ing获取要获取的数据,而不是在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( () => {
    getAPI()
      .then(() => console.log(smallData));
  }, []); // <- Add dependencies here

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

ncgqoxb0

ncgqoxb02#

更改useEffect等待getApi函数完成。

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

klh5stk13#

试试这个:

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));
  }, []);
yjghlzjz

yjghlzjz4#

首先,console.log应该显示{},因为这是smallData的初始状态,并且getAPI将异步执行,这没有什么错。
但是对于没有数据传递给子组件的问题,可能是因为您将smallData设置为{ data: *api response* },可能您希望smallData作为API响应,而不是具有data属性的对象。
我建议将console.log(smallData)放在return语句之前,以便在每次呈现时查看其内容。
如果仍然遇到问题,请添加SmallBox组件代码,也许问题就在那里

nimxete2

nimxete25#

React set State钩子是异步调用的,因此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);
     }
   }, []);

相关问题