如何避免让不再有用的异步thunk(应用程序不再期望它)无法更新状态



我的单页应用程序(React+Redux(上有以下模式。

每次在应用程序上加载页面时,它都会运行。用户导航到一个特定的页面,loadPageThunk就会被调度。页面的初始状态向用户显示一个微调器。例如,这在博客文章页面中使用。

这个thunk将获得一些异步数据(博客文章(,然后显示包含这些数据的页面。

它运行良好。当用户导航离开页面时。useEffect分派RESET动作以将状态重置回其初始值。

我的问题是:

如果异步调用需要很长时间才能完成,并且用户导航离开,该怎么办?这将造成一个问题,因为现在有一个悬而未决的承诺将在一个意想不到的时间内完成。如何防止该完成更新我的状态?

想象一下异步调用需要10秒才能完成的以下步骤:

#### FIRST PAGE LOAD ####
USER VISITS blog/slug-1
loadPageThunk() IS DISPATCHED
blogPost1 STARTS GETTING FETCHED (WILL TAKE 10 SECONDS)
USER NAVIGATES AWAY
#### SECOND PAGE LOAD ####
USER VISITS blog/slug-2
blogPost2 STARTS GETTING FETCHED (WILL TAKE 10 SECONDS)
USER IS STILL SEEING SPINNER
blogPost1 (FROM THE PREVIOUS VISIT) HAS COMPLETE AND WILL UPDATE THE STATE
USER NOW SEES blog/slug-2 WITH THE DATA FROM blogPost1 WHICH IS AN ERROR
blogPost2 WILL EVENTUALLY COMPLETE AND USER WILL SEE A CONTENT FLICKER ON THE PAGE

问题

如何避免不再有用的待定承诺无法更新状态?

这个问题目前没有出现在我的应用程序中,但我认为一个好的设计应该考虑到这一点。

我是否应该为我的LOAD_PAGE周期添加一个ID,以便在ID不匹配时允许callbacks / async code更新状态之前检查当前周期的ID?人们通常是如何处理的?

就我个人而言,我将博客数据存储为由id和collections键控的entities(帖子、评论等(。集合只是特定页面上的post-id数组。

例如,

{
entities: {
posts: {
1: {...},
2: {...}
},
comments: {
123: {...},
999: {...}
}
},
collections: {
"blog/slug-1": [99,98,97...],
"blog/slug-2": [89,88,87...],
}
}

这种结构意味着,无论是否为当前页面,每个页面都可以将其数据保存在正确的位置。这也意味着每个页面都可以选择自己的数据,并可以查看该状态中是否已经存在该数据。

createAsyncThunk返回的promise附带了一个abort()方法,可以用来"取消"promise。请参阅跑步时取消。您可以在清理中调用abort()以防止thunk为fulfilled

在reducers中,如果您正在为thunk处理rejected情况,那么您可以为错误名称为AbortError的情况添加一个异常,而不执行任何操作。

扩展一下您的具体情况:一个很好的经验法则是,如果您在卸载组件时发现自己正在"重置"状态,那么它最初应该只是本地组件状态。

最新更新