我正在尝试了解React Hooks,并遇到了一个问题。我想获取数据,先显示30个条目,然后在后台获取其余数据。我的逻辑:
useEffect(() => {
(async function () {
setIsLoading(true);
try {
const data = sortById(await fetch('url'));
const prep = await prepareData(data, (pageNumber - 1) * elementsPerPage, pageNumber * elementsPerPage);
setData(prep);
setIsLoading(false);
const backgroundData = await fetchMissingData(prep, elementsPerPage)
setData(backgroundData);
} catch (e) {
setError(e);
setIsLoading(false);
}
})();
}, [])
data
是来自API的响应,那么我正在使用它向prepareData中的对象添加一些内容-该对象本身正在调用另一个API,因此当所有请求完成时
return Promise.all(result).then(done => {
return done;
})
我正在获取对象数组,但是只有前30个对象充满了我需要的数据。准备好数据后,我将状态data
设置loading
为false。在那一刻,数据应该在页面上呈现(?)。然后,我将在后台获取其余数据,而无需再次获取相同的数据(前30个条目),并data
针对我在应用程序中需要的每个条目再次进行设置。
问题在于,数据是在最后一次渲染之后呈现的setData
-应用程序正在等待每次提取完成。我的逻辑错误在哪里?
setState
,就像在类组件中一样,它是异步调用(它不会立即起作用,但会告诉组件应使用不同的上下文再次呈现)。
例如,
useEffect(() => {
(async function () {
setIsLoading(true);
try {
setIsLoading(false);
...
} catch (e) {
setError(e);
setIsLoading(false);
}
})();
}, [])
isLoading
永远不会出现true
在它的组件中,导致您同时给它true
和两者带来相同的效果false
(假设您的代码可以逐行工作,而JS无法保证,并且您可能会遇到副作用)。同样的事情是data
因为您打了setData
两次电话
因此,您可以考虑将效果分为两个效果,而isLoading
则是第二个效果要运行的标志
useEffect(() => {
(async function () {
setIsLoading(true);
try {
const data = sortById(await fetch('url'));
const prep = await prepareData(data, (pageNumber - 1) * elementsPerPage, pageNumber * elementsPerPage);
setData(prep);
} catch (e) {
setError(e);
setIsLoading(false);
// in case there is e at first effect,second effect wont run
}
})();
}, [])
useEffect(() => {
if (isLoading) {
(async function () {
try {
//data now is equal to prep
const backgroundData = await fetchMissingData(data, elementsPerPage)
setData(backgroundData);
} catch (e) {
setError(e);
}
})();
setIsLoading(false);
}
}, [isLoading, data])
如果isLoading
标志已经用于UI渲染或其他用途,并且不能作为第二效果的标志,则可以创建唯一isSecondEffectShouldRun
或类似的标志(使用data
它本身将导致无限循环...)
希望对您有所帮助:)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句