Javascript 为什么非空数组的长度为0
有一个代码,我在其中通过数据创建链接并放入数组:Javascript 为什么非空数组的长度为0,javascript,reactjs,lodash,Javascript,Reactjs,Lodash,有一个代码,我在其中通过数据创建链接并放入数组: 功能博客(道具){ 常量链接=[]; props.ids.forEach(id=>{ 获取(`${root}/api/blog/${id}`) .then(res=>res.json()) 。然后(res=>{ const link={{uu.get(res,'blog.name','')} 链接。推(链接); }) }); console.log(links.length)//0 返回( Блоги {links}{/*无*/} ); } 当
功能博客(道具){
常量链接=[];
props.ids.forEach(id=>{
获取(`${root}/api/blog/${id}`)
.then(res=>res.json())
。然后(res=>{
const link={{uu.get(res,'blog.name','')}
链接。推(链接);
})
});
console.log(links.length)//0
返回(
Блоги
{links}{/*无*/}
);
}
当我在控制台链接时:
为什么
links.length==0
以及如何修复它?您需要使用两个react挂钩<代码>使用状态用于链接数组,使用效果用于获取函数。TL;博士
执行以下更改:
async function Blogs(props) {
const links = [];
for(let id of props.ids){
const res = await fetchLink(id);
const link = <Link to={`/blog/${id}`}>{_.get(res, 'blog.name', '')}</Link>
links.push(link);
}
const fetchLink = async(id) =>{
const result = await fetch(`${root}/api/blog/${id}`);
return result.json();
}
console.log(links.length) // 0
return (
<div className="profile-blogs">
<div className="a">Блоги</div>
<div className="b">
{links} {/* nothing */}
</div>
</div>
);
}
异步函数博客(道具){
常量链接=[];
for(让props.id的id){
const res=等待获取链接(id);
const link={{uu.get(res,'blog.name','')}
链接。推(链接);
}
const fetchLink=async(id)=>{
const result=await fetch(`${root}/api/blog/${id}`);
返回result.json();
}
console.log(links.length)//0
返回(
Блоги
{links}{/*无*/}
);
}
但是为什么我的代码不起作用呢
JS是异步的,它不等待任何异步语句完成。因此,如果处理不当,将执行异步操作之后要执行的下一行代码。
forEach
方法不会连续执行异步代码(我猜这是您的假设)。因此在循环中,所有元素都将一个接一个地运行(调用fetch
API),而无需等待前一个元素完成(这就是JS的工作方式)。
最后到达下一行,即console.log(links.length)
,它打印0
,因为在执行这一行之前,您的API调用从未完成
另一个要点是:
在组件中执行此类代码是不可取的,因为每次状态更新和组件重新呈现时,都会重新执行此类代码。
此类代码应该作为sideEffect
执行,可能使用useffect
钩子。
因此,代码块仅在需要时执行,而不是每次呈现组件时执行。
fetch()
是异步的。HTTP请求完成时,.then()
函数将运行。您的控制台.log
是在获取
之后写入的,但实际上获取
是在之后调用的,因为获取需要时间。。。因此,当fetch
代码仍在等待数据时,代码移到控制台.log
。这是一个简单的解释。你需要观看。这回答了你的问题吗?“这不是在React中异步获取和呈现的方式。”Emilebergron同意。见我的最后一段。我修改代码的第一步是让他理解异步代码是如何工作的。这绝对不是反应式的做法。不幸的是,这会让你的答案产生误导。是的。。。我会更新我的答案。。