You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS:使用firestoreConnect从Props存对象到State遇异常求助

解决React-Redux-Firebase加载Firestore设备数据的问题

看起来你遇到的核心问题是异步数据加载的时机处理不当,以及初始渲染时auth.uid未就绪导致的Firestore查询无效。咱们一步步拆解解决:

问题根源分析

  1. Auth数据加载延迟:组件初始化时,props.auth.uid可能还未从Firebase Auth加载完成,导致firestoreConnect中的查询条件无效,无法获取到devices数据。
  2. 异步数据未做加载判断:直接访问devices的属性(比如name)时,数据可能还在加载中,此时devices是undefined或空数组,自然会抛出"Can't read property 'name' of undefined"错误。
  3. 不必要的State同步:在componentDidMount中把props.devices存入state是冗余操作,redux的props是响应式的,存到state反而会导致数据不同步。

具体修复方案

1. 修复Firestore查询条件,确保Auth就绪后再发起查询

修改firestoreConnect,只有当auth.uid存在时才发起查询,避免无效请求:

firestoreConnect((props) => {
  // 仅当用户已登录(uid存在)时,才查询对应设备
  return props.auth.uid ? [
    { collection: 'devices', where: [ ['managerId', '==', props.auth.uid] ] }
  ] : [];
})

2. 移除冗余的State同步逻辑

删掉componentDidMount中的setState操作,直接使用props中的devices即可,redux会自动同步数据更新:

// 删掉这段代码
componentDidMount() { 
  this.setState({ dev: this.props.devices }) 
}

3. 渲染时添加数据加载判断

在render方法中先检查devices是否存在且有数据,再进行渲染,避免报错:

render() {
  const {devices, profile, classes, className, ...rest } = this.props;
  const rootClassName = classNames(classes.root, className);
  // 判断设备数据是否加载完成
  const hasLoadedDevices = devices && devices.length > 0;

  return (
    <Paper {...rest} className={rootClassName} >
      <div className={classes.content}>
        <div className={classes.details}>
          <Typography className={classes.title} variant="body2" > Device </Typography>
          {/* 根据加载状态显示不同内容 */}
          <Typography className={classes.value} variant="h3" >
            {hasLoadedDevices ? devices[0].name : 'Loading devices...'}
          </Typography>
        </div>
        <div className={classes.iconWrapper}>
          <MoneyIcon className={classes.icon} />
        </div>
      </div>
      <div className={classes.footer}>
        {hasLoadedDevices ? (
          // 遍历设备状态
          devices.map(device => (
            <Typography 
              key={device.id} 
              className={device.isError ? classes.deviceError : classes.deviceOk} 
              variant="body2"
            >
              {device.isError ? <Error /> : <Done />} {device.isError ? 'Error' : 'Running'}
            </Typography>
          ))
        ) : (
          <Typography variant="body2">Loading device status...</Typography>
        )}
      </div>
    </Paper>
  );
}

4. 额外检查:确认Store配置正确

确保你的redux store已经正确集成了redux-firestore和react-redux-firebase,示例配置如下:

import { createStore, combineReducers, compose } from 'redux';
import { reactReduxFirebase, firebaseReducer } from 'react-redux-firebase';
import { reduxFirestore, firestoreReducer } from 'redux-firestore';
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';

// 你的Firebase配置
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  // ...其他配置
};

firebase.initializeApp(firebaseConfig);

// React-Redux-Firebase配置
const rrfConfig = {
  userProfile: 'users',
  useFirestoreForProfile: true // 若用Firestore存储用户信息需开启
};

// 合并reducers
const rootReducer = combineReducers({
  firebase: firebaseReducer,
  firestore: firestoreReducer,
  // ...你的其他reducers
});

// 创建带Firebase的store
const createStoreWithFirebase = compose(
  reactReduxFirebase(firebase, rrfConfig),
  reduxFirestore(firebase)
)(createStore);

const store = createStoreWithFirebase(rootReducer);

export default store;

核心逻辑说明

  • 当用户登录完成后,props.auth.uid会被更新,此时firestoreConnect会自动重新计算查询条件,发起正确的Firestore请求获取设备数据。
  • 直接使用props中的devices,redux会在数据更新时自动触发组件重新渲染,无需手动同步到state。
  • 添加加载状态判断,避免在数据未就绪时访问undefined的属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:37:01