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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:50:23