React Redux中请求返回前如何正确显示空div?
如何在Redux Dispatch请求返回前正确显示空div
嘿,我来帮你搞定这个问题~你当前的代码其实有个小疏漏:初始状态下fetchedPosts是空数组,这时候你会直接显示空div,但用户根本分不清这是请求还在加载中还是加载完成后真的没有数据。要解决这个问题,我们需要给Redux的状态加上「加载状态标记」,这样就能精准区分不同阶段的显示内容了。
步骤1:给Redux的Posts状态添加加载标记
首先,在你的posts reducer里,给初始状态加上isLoading和可选的error字段,用来追踪请求的状态:
// reducers/postsReducer.js const initialState = { recommendedPosts: [], isLoading: false, // 标记是否正在加载 error: null // 存储请求错误信息(可选) }; const postsReducer = (state = initialState, action) => { switch (action.type) { // 请求开始时,设置isLoading为true case 'FETCH_RECOMMENDED_POSTS_REQUEST': return { ...state, isLoading: true, error: null }; // 请求成功时,更新数据并关闭加载状态 case 'FETCH_RECOMMENDED_POSTS_SUCCESS': return { ...state, isLoading: false, recommendedPosts: action.payload }; // 请求失败时,关闭加载状态并存储错误信息 case 'FETCH_RECOMMENDED_POSTS_FAILURE': return { ...state, isLoading: false, error: action.payload }; default: return state; } }; export default postsReducer;
如果你用的是Redux Toolkit(更推荐的现代写法),代码会更简洁:
// redux/slices/postsSlice.js import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import api from '../api'; // 假设你的API请求工具在这里 export const fetchRecommendedPosts = createAsyncThunk( 'posts/fetchRecommendedPosts', async ({ token }) => { const response = await api.get('/recommended-posts', { headers: { Authorization: `Bearer ${token}` } }); return response.data; } ); const postsSlice = createSlice({ name: 'posts', initialState: { recommendedPosts: [], isLoading: false, error: null }, extraReducers: (builder) => { builder .addCase(fetchRecommendedPosts.pending, (state) => { state.isLoading = true; state.error = null; }) .addCase(fetchRecommendedPosts.fulfilled, (state, action) => { state.isLoading = false; state.recommendedPosts = action.payload; }) .addCase(fetchRecommendedPosts.rejected, (state, action) => { state.isLoading = false; state.error = action.error.message; }); } }); export default postsSlice.reducer;
步骤2:更新你的action创建函数
如果用的是传统redux-thunk,需要更新fetchRecommendedPosts来分发请求状态的action:
// redux/actions/postsActions.js import api from '../api'; export const fetchRecommendedPosts = ({ token }) => async (dispatch) => { // 先分发请求开始的action dispatch({ type: 'FETCH_RECOMMENDED_POSTS_REQUEST' }); try { const response = await api.get('/recommended-posts', { headers: { Authorization: `Bearer ${token}` } }); // 请求成功,分发成功action dispatch({ type: 'FETCH_RECOMMENDED_POSTS_SUCCESS', payload: response.data }); } catch (error) { // 请求失败,分发失败action dispatch({ type: 'FETCH_RECOMMENDED_POSTS_FAILURE', payload: error.message }); } };
步骤3:修改组件逻辑,根据加载状态显示内容
现在你的组件可以通过isLoading来区分不同阶段,精准控制显示空div(或加载动画)、数据、无数据或错误信息:
import React, { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { fetchRecommendedPosts } from "../redux/actions/postsActions"; import Post from "../components/sharedComponents/Post"; const RecommendedUserPostsPage = () => { const dispatch = useDispatch(); const { token } = useSelector((state) => state.auth); // 从state中取出加载状态、错误和数据 const { recommendedPosts: fetchedPosts, isLoading, error } = useSelector((state) => state.posts); // 注意:把dispatch和token加入依赖数组,避免lint警告,同时token变化时能重新请求 useEffect(() => { dispatch(fetchRecommendedPosts({ token })); }, [dispatch, token]); let content; if (isLoading) { // 请求进行中:显示你要的空div,或者换成加载动画也可以 content = <div />; } else if (error) { // 请求失败:可选显示错误提示 content = <div>加载推荐帖子失败:{error}</div>; } else if (fetchedPosts.length > 0) { // 有数据:渲染帖子,记得加唯一key! content = fetchedPosts.map((post) => ( <Post key={post.id} postData={post} /> )); } else { // 加载完成无数据:可以显示空div,或者友好提示 content = <div>暂无推荐帖子</div>; } return <div style={{ margin: "5em" }}>{content}</div>; }; export default RecommendedUserPostsPage;
几个关键注意点:
- 区分加载状态 vs 无数据状态:这是你原来代码的核心问题,加上
isLoading后就能明确区分“正在加载”和“加载完没数据”,用户体验会更好。 - useEffect的依赖数组:一定要把
dispatch和token加进去,dispatch在Redux中是稳定的,不会导致重复渲染;而token变化时,我们需要重新请求推荐帖子。 - key属性:用
map渲染组件时,必须给每个子组件加唯一的key(比如帖子的id),这是React的性能优化要求,也能避免控制台警告。
内容的提问来源于stack exchange,提问作者Lola
相关产品推荐
相关产品推荐

