了解钩子在 React 中设置状态



我正在尝试了解 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它的组件中,因为你给它truefalse的效果是一样的(假设你的代码将逐行工作,这不能保证与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本身会导致无限循环......

希望它对您有所帮助:)

相关内容

  • 没有找到相关文章