React组件无法访问Redux Store数据问题求助
问题:Redux Store中已有Firestore数据,但组件无法正确访问
你遇到的核心问题是Redux状态的访问路径错误,以及组件中对数据状态的判断逻辑有误,具体分析和修复方案如下:
问题诊断
- 状态结构不匹配:你的
LoadDataFromFireStoreslice的初始状态是{ data: [] },这意味着state.fireStore是一个包含data数组的对象,而非直接的数组。但你在组件中直接取了state.fireStore并尝试调用map方法——对象无法执行数组的map操作,导致你误以为数据未加载。 - 加载状态判断失效:
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
相关产品推荐
相关产品推荐

