React异步获取API数据后,如何正确赋值变量避免undefined?
问题原因及解决方案
问题根源
- 普通变量无法触发组件渲染:你用
let shareUrl声明的是普通变量,React组件每次重新渲染时都会重新声明这个变量并初始化为undefined。就算异步fetch完成后给它赋值,也不会触发组件重新渲染,页面上的按钮始终拿到的是初始的undefined。 - setState的异步特性:
setDetails(detailData)是异步操作,执行后details不会立刻更新,此时details.id还是初始空对象的undefined,所以拼接出来的shareUrl本身就有问题,而且后续组件渲染时shareUrl又会被重置。
解决方案
方案一:直接在渲染时拼接URL(推荐)
不需要单独声明shareUrl变量,直接在传递按钮props时用details.id拼接,利用setDetails触发的组件重新渲染来更新URL:
// 替换所有ShareBtn的shareUrl属性 <PinterestShareBtn borderRadius={borderRadius} shareUrl={`https://dishlyst.netlify.app/recipe/${details?.id || ''}`}/> <TwitterShareBtn borderRadius={borderRadius} shareUrl={`https://dishlyst.netlify.app/recipe/${details?.id || ''}`}/> <FacebookShareBtn borderRadius={borderRadius} shareUrl={`https://dishlyst.netlify.app/recipe/${details?.id || ''}`}/> <LineShareBtn borderRadius={borderRadius} shareUrl={`https://dishlyst.netlify.app/recipe/${details?.id || ''}`}/> <LinkedInShareBtn borderRadius={borderRadius} shareUrl={`https://dishlyst.netlify.app/recipe/${details?.id || ''}`}/> <WhatsAppShareBtn borderRadius={borderRadius} shareUrl={`https://dishlyst.netlify.app/recipe/${details?.id || ''}`}/>
这里用details?.id是可选链操作符,避免details为空时出现Cannot read property 'id' of undefined的错误,|| ''则保证URL不会出现undefined后缀。
方案二:将shareUrl改为状态变量
用useState管理shareUrl,这样更新时会触发组件重新渲染,同时直接用接口返回的detailData.id(避免依赖异步更新的details):
// 替换原来的let shareUrl; const [shareUrl, setShareUrl] = useState(''); const fetchDetails = async () => { const data = await fetch(`https://api.spoonacular.com/recipes/${params.name}/information?apiKey=${process.env.REACT_APP_API_KEY}`); const detailData = await data.json(); setDetails(detailData); // 直接用detailData.id,不用等setDetails更新 setShareUrl(`https://dishlyst.netlify.app/recipe/${detailData.id}`); }
这样当fetch完成后,shareUrl状态更新,组件重新渲染,按钮就能拿到正确的URL了。
内容的提问来源于stack exchange,提问作者Christoper Chamberlain
相关产品推荐
相关产品推荐

