Redux Thunk中追加新状态至旧状态时重复数据问题求助
分页获取帖子时Redux状态重复添加初始数据的问题
在使用Redux Toolkit的createAsyncThunk和createSlice实现分页获取帖子功能时,遇到初始请求返回的payload被重复添加到state.allPosts中的问题,导致数据重复。
相关代码
完整的slice代码:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' import axios from 'axios' let url = 'http://localhost:3000/api/v1/posts' const initialState = { allPosts: [], isLoading: false, isError: false, } export const getAllPost = createAsyncThunk('allPosts/getAllPost', async (page, thunkAPI) => { console.log(page) try { const { data } = await axios.get(`${url}?page=${page}`) return data.posts } catch (error) { console.log(error) } }) const allPostSlice = createSlice({ name: 'allPosts', initialState, reducers: {}, extraReducers: { [getAllPost.pending]: (state) => { state.isLoading = true }, [getAllPost.fulfilled]: (state, { payload }) => { console.log(payload) state.allPosts = [...state.allPosts, ...payload] state.isLoading = false }, [getAllPost.rejected]: (state) => { state.isLoading = false state.isError = true }, }, }) export default allPostSlice.reducer
出现问题的核心代码片段:
[getAllPost.fulfilled]: (state, { payload }) => { console.log(payload) state.allPosts = [...state.allPosts, ...payload] state.isLoading = false },
解决方法
1. 检查并避免重复触发异步请求
最常见的原因是组件中重复调用了dispatch(getAllPost()),比如:
useEffect未设置正确的依赖数组,导致每次组件渲染都触发请求;- React严格模式在开发环境下会重复执行副作用,导致请求触发两次。
修改组件中的请求触发逻辑:
确保初始化请求只执行一次,可通过useRef标记是否已请求过:
import { useRef, useEffect } from 'react' import { useDispatch } from 'react-redux' import { getAllPost } from './path/to/your/slice' function PostList() { const dispatch = useDispatch() const hasInitiatedFetch = useRef(false) useEffect(() => { if (!hasInitiatedFetch.current) { dispatch(getAllPost(1)) hasInitiatedFetch.current = true } }, [dispatch]) // 其他组件逻辑 }
如果是React严格模式导致的开发环境重复触发,生产环境不会有这个问题,上述useRef方法同样能在开发环境避免重复请求。
2. 在状态更新时做去重处理
如果无法避免重复请求(或后端可能返回重复数据),可以在状态更新时根据帖子唯一标识(比如id)过滤重复项:
[getAllPost.fulfilled]: (state, { payload }) => { console.log(payload) // 过滤掉已存在于allPosts中的帖子 const uniqueNewPosts = payload.filter( newPost => !state.allPosts.some(existingPost => existingPost.id === newPost.id) ) state.allPosts = [...state.allPosts, ...uniqueNewPosts] state.isLoading = false },
这样即使请求被重复触发,也不会把重复数据添加到状态中。
内容的提问来源于stack exchange,提问作者Jcarlo Senin
相关产品推荐
相关产品推荐

