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

React组件无法访问Redux Store数据问题求助

问题:Redux Store中已有Firestore数据,但组件无法正确访问

你遇到的核心问题是Redux状态的访问路径错误,以及组件中对数据状态的判断逻辑有误,具体分析和修复方案如下:

问题诊断

  1. 状态结构不匹配:你的LoadDataFromFireStore slice的初始状态是{ data: [] },这意味着state.fireStore是一个包含data数组的对象,而非直接的数组。但你在组件中直接取了state.fireStore并尝试调用map方法——对象无法执行数组的map操作,导致你误以为数据未加载。
  2. 加载状态判断失效:productsData是一个对象(初始状态为{ data: [] }),属于真值,因此你的productsData ? ... : <Spin>判断永远会进入map分支,即使数据还在加载中。

修复方案

1. 修正组件中的状态访问路径

在useSelector中直接获取fireStore下的data数组:

const productsData = useSelector(state => state.fireStore.data);

2. 优化加载状态判断

基于数组长度判断是否显示加载组件,或者更严谨的方式是给slice添加loading状态:

方式一:基于数组长度判断(快速修复)

{productsData.length > 0 ? (
  productsData.map(productData => (
    <Col className='GridColumn' key={productData.id}>
      <Product data={productData} />
    </Col>
  ))
) : (
  <Spin size='large' />
)}

方式二:给slice添加加载状态(推荐)

修改你的slice代码,添加loading和error状态,让异步流程更清晰:

import { createSlice } from '@reduxjs/toolkit'
import { firebaseFireStoreDB } from '../../FirebaseConfiguration/Firebase';
import { collection, getDocs } from 'firebase/firestore';

const initialState = { 
  data: [],
  loading: false,
  error: null
};

const LoadDataFromFireStore = createSlice({
  name: "DataFromFireStore",
  initialState,
  reducers: {
    loadStart: (state) => {
      state.loading = true;
      state.error = null;
    },
    loadSuccess: (state, action) => {
      state.loading = false;
      state.data = action.payload;
    },
    loadFailure: (state, action) => {
      state.loading = false;
      state.error = action.payload;
    }
  }
})

export function getProducts() {
  return async (dispatch) => {
    dispatch(loadStart());
    try {
      const collectionRef = collection(firebaseFireStoreDB, "products");
      const productSnapshot = await getDocs(collectionRef);
      const productdata = productSnapshot.docs.map(doc => ({ 
        ...doc.data(), 
        id: Number(doc.id) 
      }));
      dispatch(loadSuccess(productdata));
    } catch (error) {
      dispatch(loadFailure(error.message));
      console.log("Error while fetching... " + error);
    }
  }
}

export const { loadStart, loadSuccess, loadFailure } = LoadDataFromFireStore.actions;
export default LoadDataFromFireStore.reducer;

然后在组件中使用这些状态:

function Products() {
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(getProducts());
  }, []);

  const { data: productsData, loading, error } = useSelector(state => state.fireStore);

  if (loading) return <Spin size='large' />;
  if (error) return <div>加载失败:{error}</div>;

  return (
    <div className='ProductsContainer'>
      <h2 style={{ textAlign: "center" }}>OUR PRODUCTS</h2>
      <Row gutter={[20, 35]} className='GridRowStyling'>
        {productsData.map(productData => (
          <Col className='GridColumn' key={productData.id}>
            <Product data={productData} />
          </Col>
        ))}
      </Row>
    </div>
  )
}

3. 优化异步Action的写法

避免同时使用await和.then/.catch,改用try/catch让代码更简洁易读,这也是上面slice修改中已经调整的部分。

额外检查

确认你的Redux Store配置中,fireStore对应的reducer确实是LoadDataFireStore.reducer——从你的代码看是正确的,这部分没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 18:22:03