You need to enable JavaScript to run this app. 从Redux获取数据时,函数组件的加载屏幕为何未正常显示
优惠活动
大模型
产品
解决方案
定价
更多

从Redux获取数据时,函数组件的加载屏幕为何未正常显示

问题原因

你现在的写法从根本上就没把loading的状态和异步请求的执行顺序对齐,直接导致加载屏根本没机会被渲染:

1. setLoading(false) 位置完全错位

梳理你当前useEffect的实际执行顺序:

  • 进入effect后,首先定义异步函数anyNameFunction,这时候函数内部的代码完全不会运行
  • 调用anyNameFunction()时,函数刚走到第一行setLoading(true),就遇到了await dispatch(...) —— 此时异步函数会立刻挂起后续执行流程,给外部返回一个pending状态的Promise,根本不会停下来等请求走完
  • 函数挂起后,代码立刻顺次执行effect里剩下的同步语句:也就是你写在外面的setLoading(false)

从React 18开始,所有同一同步执行上下文里的连续state更新都会被自动批处理合并,不会触发多次独立渲染。你先后执行的setLoading(true)和setLoading(false)同属一个同步任务,最终合并渲染时拿到的loading值直接就是false,loading=true的状态从来没有被单独提交给React渲染管线,加载屏自然不会出现。
至于你能看到等了一会数据才出来的效果,是因为异步请求完成、Redux状态更新触发重渲染时,loading早就被设成了false,直接跳过加载屏渲染了内容区域。

2. 异步等待可能完全失效

如果你写的fetchAddressList是Redux Thunk结构,但没有在最外层返回内部的请求Promise,那么dispatch(fetchAddressList())的返回值是undefined。此时await undefined会立刻进入完成状态,根本等不到接口请求真正结束,哪怕你调整了setLoading的位置,也会出现关loading太快的问题。

正确修改方式

把所有loading状态的操作全部收敛到异步函数内部,通过try/finally结构保证状态操作和异步执行顺序完全绑定,删掉异步函数外部的setLoading(false)调用:

useEffect(() => {
  async function loadAddressList() {
    setLoading(true);
    try {
      // 等待dispatch返回的Promise完全解决
      await dispatch(fetchAddressList());
    } catch (err) {
      console.log('地址列表加载失败', err);
    } finally {
      // 不管请求成功/失败,走完流程再关闭loading
      setLoading(false);
    }
  }
  loadAddressList();
}, []);

这里要确保你写的fetchAddressList是标准Thunk结构,一定要在外层return内部的异步逻辑,不然await是拿不到等待结果的:

// 错误写法示例:没有return,dispatch之后返回undefined
export const fetchAddressList = () => async (dispatch) => {
  const res = await axios.get('/address/list');
  dispatch({ type: 'SET_ADDRESS_LIST', payload: res.data });
}

// 正确写法:有返回Promise,await可以正常等待
export const fetchAddressList = () => {
  return async (dispatch) => {
    try {
      const res = await axios.get('/address/list');
      dispatch({ type: 'SET_ADDRESS_LIST', payload: res.data });
    } catch (err) {
      dispatch({ type: 'SET_ADDRESS_ERROR', payload: err });
    }
  }
}
额外排查

如果调整完上述逻辑后加载屏还是显示异常,可以检查布局:你将全屏高度的加载View放在ScrollView内部,如果没有给ScrollView设置contentContainerStyle={{ flexGrow: 1 }},ScrollView的内容会根据子元素总高度拉伸,可能导致初始滚动位置偏移,把加载屏挤到视口外看不到。


内容的提问来源于stack exchange,提问作者Kerry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 18:27:09