为什么ReactJS中Redux存储的Firebase拉取数据无法正常渲染?
问题根源
你的异步调用逻辑存在等待不完整的问题:
- 外层
await仅等待了listAll()方法执行完成,但forEach循环内的所有getDownloadURL()都是独立的异步Promise,你没有等待这些Promise全部执行完成就执行了dispatch - 触发dispatch时
list还是空数组,后续getDownloadURL()陆续执行完成后才将数据push进同一个数组对象,由于数组的引用地址没有变化,Redux的状态比较逻辑会认为状态未发生变更,因此不会触发组件重新渲染 - 控制台展开数组能看到数据、Redux DevTools能看到数据,都是因为二者读取的是数组引用的实时最新值,和dispatch时的状态不是同一时间快照
修复方案
1. 修正thunk异步逻辑
收集所有getDownloadURL的Promise,用Promise.all等待全部执行完成后再生成新数组触发dispatch,修正后的代码如下:
try { const listRes = await storage .ref() .child(path) .listAll() // 收集所有获取下载地址的异步任务 const filePromiseList = listRes.items.map(async (item) => { const url = await storage .ref() .child(item.fullPath) .getDownloadURL() return { name: item.name, url } }) // 等待所有异步任务执行完成,拿到最终文件列表 const finalList = await Promise.all(filePromiseList) dispatch(getFileActionSuccess(finalList)) } catch (err) { // 补充错误处理逻辑 console.error('拉取文件列表失败', err) }
2. 修正组件内请求触发逻辑
你当前直接在Page组件顶层调用getFiles(),会导致每次组件渲染都重复发起请求,需要用useEffect包裹限制触发时机:
import { useEffect } from 'react' function Page() { useEffect(() => { // 仅组件挂载时发起一次请求,如果有依赖参数可以加到依赖数组里 getFiles() }, []) return <FilesList /> }
3. 确认Reducer逻辑正确
检查处理getFileActionSuccess的Reducer,必须返回全新的数组对象,不能直接修改原state:
// 正确写法 case 'GET_FILE_SUCCESS': return { ...state, files: action.payload } // 错误写法(不会触发更新) // case 'GET_FILE_SUCCESS': // state.files = action.payload // return state
内容的提问来源于stack exchange,提问作者M4jorL3gend
相关产品推荐
相关产品推荐

