React Native中使用TanStack React Query时,首次挂载页面未调用refetch()却触发isRefreshing导致RefreshControl显示加载状态的问题
React Native中使用TanStack React Query时,首次挂载页面未调用refetch()却触发isRefreshing导致RefreshControl显示加载状态的问题
兄弟,我来帮你捋捋这个头疼的问题!你遇到的情况其实是对React Query里isRefreshing这个状态的逻辑和用法没摸透,再加上默认配置的影响,我给你拆解清楚:
首先得搞懂React Query里两个加载状态的本质区别:
isLoading:专门对应**首次获取数据(没有缓存数据时)**的加载状态,比如第一次打开页面、缓存过期且无可用数据时的加载。isRefreshing:是用来标识已有可用缓存数据的情况下,后台正在偷偷拉取最新数据的状态——正常来说,首次打开页面没缓存的话,这个状态应该是false才对。
那你为啥首次打开页面isRefreshing就变成true了?大概率是这两个原因:
- 缓存残留触发自动刷新:如果你之前打开过这个页面(哪怕是测试的时候),React Query已经缓存了
['user']这个key的数据,当你再次进入页面时,React Query默认的refetchOnMount: true配置会自动在后台重新拉取数据,这时候isRefreshing就会被置为true。哪怕你觉得是“第一次”打开,说不定之前的缓存没清干净,也会触发这个逻辑。 - 状态逻辑混用:你直接把
isRefreshing绑定给了RefreshControl的refreshing属性,但RefreshControl本来是用来处理下拉刷新这个主动操作的状态,而初始加载的状态应该用isLoading来控制,混在一起就会导致初始加载时也显示下拉加载的样式。
给你几个可行的解决办法,你按需选:
- 严格区分两种状态的使用场景
把RefreshControl的刷新状态改成只响应真正的下拉刷新操作,初始加载的状态用其他组件(比如页面顶部的加载提示)来处理:
return ( <FlatList data={data} renderItem={renderItem} keyExtractor={item => item.id} refreshControl={ <RefreshControl // 只有非初始加载的后台刷新时,才让RefreshControl显示加载 refreshing={isRefreshing && !isLoading} onRefresh={refetch} /> } /> )- 严格区分两种状态的使用场景
- 调整React Query的自动刷新配置
如果你不希望每次进入页面都自动后台刷新,可以在useQuery里修改refetchOnMount的配置:
不过这个要结合业务需求来,如果你的页面需要每次进入都拿最新数据,那可以保留默认值,但这时候就得用第一种方法区分状态。const { data, isLoading, isRefreshing, refetch} = useQuery({ queryKey: ['user'], queryFn: getUser, refetchOnMount: false // 关闭进入页面时的自动后台刷新 });- 调整React Query的自动刷新配置
- 清缓存做测试
先卸载重装APP或者清除缓存,确保没有残留的旧缓存数据,再测试第一次打开页面的状态,排除缓存导致的干扰。如果这时候isRefreshing还是true,那你得检查下getUser这个请求函数有没有自动重试、重复调用的逻辑。
- 清缓存做测试
总结一下,核心就是把两个加载状态的职责分清楚,再根据业务需求调整配置和状态判断逻辑,就能解决你遇到的首次打开页面就显示下拉加载的问题啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

