使用 UseEffect Hook 获取 API
Posted
技术标签:
【中文标题】使用 UseEffect Hook 获取 API【英文标题】:Using UseEffect Hook to Fetch 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 调用和响应状态更改都是异步的,您可以在下一行打印状态值并查看更新
【参考方案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】:在记录数据之前尝试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( () =>
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);
, []);
【讨论】:
以上是关于使用 UseEffect Hook 获取 API的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 useEffect() 更改 React-Hook-Form defaultValue?
我无法获取 localStorage 数据,我正在使用 useEffect Hook
React Hook useEffect :使用 axios 和 async await .api 获取数据,调用连续相同的 api
如何在 React Native 应用程序中使用 React hook useEffect 为每 5 秒渲染设置间隔?