React-Redux结合Firebase开发时,如何基于当前登录用户UID高效获取匹配的关联公司数据
现有代码的核心问题定位
你当前的查询失效是几个硬性逻辑错误叠加导致的:
- 语法疏漏:firestoreConnect返回的查询数组中,
company_roles查询对象和company查询对象之间漏了逗号,直接导致数组结构解析失败,查询配置无法正常生效 - 时序错误:firestoreConnect会随组件props更新重新执行查询配置,但首次执行时
company_roles还处于异步加载状态,此时初始值为空数组/undefined,直接取它的字段做查询条件,自然拿到undefined - 字段逻辑错配:
state.firestore.ordered返回的集合查询结果永远是数组结构,哪怕只匹配到1条记录,也不存在.uid这种对象属性,取属性值自然报错- 你用来关联两个集合的核心字段是
company_id,但查询时错误匹配company_name字段,就算值取到了也没法正确关联
- 无前置判断:登录态、关联角色数据未准备完成时就发起无效查询,没有做空值拦截
可落地的修复方案
因为Firestore本身不支持跨集合的关联联表查询,需要通过分步触发查询的方式实现数据关联,核心逻辑是等依赖数据加载完成后,再发起下一级查询,不需要调整现有后端数据结构:
- 先修复firestoreConnect的查询配置,加上前置空值判断,等关联数据就绪后再动态追加公司集合的查询:
firestoreConnect((props) => { // 未登录状态不发起任何查询,避免带空uid请求 if (!props.auth.uid) return [] // 第一步:固定拉取当前登录用户对应的角色数据 const queryList = [ { collection: 'company_roles', where: [['user_id', '==', props.auth.uid]] } ] // 第二步:等角色数据加载完成、拿到关联的company_id后,再追加公司数据的查询 // 只有当角色数组存在且有值时,才发起公司查询,避免空值请求 if (props.company_roles?.length > 0) { const targetCompanyId = props.company_roles[0].company_id queryList.push({ collection: 'company', // 如果company集合的文档ID和company_id一致,用doc查询是效率最高的,只拉单条文档 doc: targetCompanyId // 如果company集合的文档内单独存储了company_id字段,就用where条件替代上面的doc配置 // where: [['company_id', '==', targetCompanyId]] }) } return queryList })
- 调整mapStateToProps的取值逻辑,注意Firestore返回结构的差异:
const mapStateToProps = (state) => { // 角色数据从ordered结构取,是固定的数组格式 const companyRoles = state.firestore.ordered.company_roles || [] // 从角色数组中取出关联的公司ID const linkedCompanyId = companyRoles[0]?.company_id return { auth: state.firebase.auth, company_roles: companyRoles, // 注意:单文档(doc方式)查询的结果会存在firestore.data结构中,不会同步到ordered数组 // 不要从ordered结构取公司数据,不然永远拿到undefined company_data: linkedCompanyId ? state.firestore.data.company?.[linkedCompanyId] : undefined } }
关键注意事项
- 不要依赖首次渲染时的props值做查询判断:firestoreConnect是响应式的,只要你把依赖的Firestore数据接到组件props上,等数据加载完成触发props更新时,配置函数会自动重新执行、发起新的查询,这个机制不需要手动写监听逻辑
- 不要混淆Firestore的两个状态存储结构:
state.firestore.ordered:只存集合查询的结果,是排序后的文档数组,适合列表类数据state.firestore.data:存所有拉取过的文档,是文档ID为键的键值对结构,单文档查询的结果必须从这里取
- 不需要把全量company集合拉到前端再做过滤:动态按company_id拉单条公司文档,既减少流量消耗,也符合权限控制的要求,避免越权拉到不属于当前用户的公司数据
内容的提问来源于stack exchange,提问作者Sky Lurk
相关产品推荐
相关产品推荐

