【发布时间】:2021-12-24 06:07:59
【问题描述】:
场景:
我有两个 api 调用,它们都对同一个状态有贡献,所以我最初所做的只是在同一个 useEffect 中等待两个 api 调用。但是,其中一个是相当慢的,所以我需要等待很长的时间来渲染页面。
const [loading, setLoading] = useState(true)
useEffect(async() => {
try{
slow_api_call_promise = await slow_api_call
quick_api_call_promise = await quick_api_call
setLoading(false)
let newState = quick_api_call_promise.data.merge(slow_api_call_promise.data)
setState(newState)
}catch(e){
setLoading(false)
//show error message
}
},[])
return <React.Fragment>
{loading ? <SpinnerComponent />: <Actual Page />}
</React.Fragment>
幸运的是,快速的实际上提供了我初始渲染所需的大部分状态,而慢速的只贡献了部分页面状态。所以为了渲染体验,我把它们分成了两个 useEffect 并为它们设置了不同的加载状态。它似乎工作。但这对我来说看起来很傻,它会渲染两次。有没有更好的方法,一种优化的方法来解决这个问题。
const [loadingWhole, setLoadingWhole] = useState(true)
const [loadingPart, setLoadingPart] = useState(true)
useEffect(async() => {
quick_api_call_promise = await quick_api_call
setLoadingWhole(false)
},[])
useEffect(async() => {
slow_api_call_promise = await slow_api_call
setLoadingPart(false)
},[])
【问题讨论】:
-
只是不要
await缓慢的 api 调用......它仍然会渲染两次,但你的代码会少很多重复 -
"这看起来很傻,它会渲染两次" - 但这正是你想要的?
-
通知您cannot pass an
asyncfunction touseEffectanyway。所以是的,只需在一个效果中进行两次调用。 -
@MikeAbeln 我必须选择这种方式,因为较慢的 api 调用大约需要 10 秒,用户不会容忍第一次绘制时间为 10 秒
-
@Bergi 是的,我需要两个 api,而较慢的那个真的很慢。所以第一个 api 将返回我想要的大部分内容,对于第二个 api,我在它试图加载的东西上放了一个加载器,所以从逻辑上讲,会有两个渲染。但只是想知道是否还有其他更清洁的方法,例如保湿,或者将这两种 useEffect 合二为一。
标签: reactjs promise render use-effect race-condition