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

如何避免重新进入React组件时重复请求导致Redux store重复填充?

你提到的在store中新增isLoaded状态标识的方案就是当前这类场景的主流处理方式,搭配Redux Toolkit实现成本很低,具体可以按下面的步骤落地:

方案1:手动维护加载状态(适配你当前axios+RTK Slice的技术栈)

首先在你的news相关slice的state中新增状态字段,基础版本(单页场景)的结构如下:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import axios from 'axios'

// 异步请求thunk
export const getNewsInitial = createAsyncThunk(
  'news/getInitial',
  async (page) => {
    const res = await axios.get(`/api/news?page=${page}`)
    return res.data
  }
)

const initialState = {
  list: [],
  isLoading: false,
  isLoaded: false, // 核心标记:当前页数据是否已经加载完成
  error: null
}

const newsSlice = createSlice({
  name: 'news',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(getNewsInitial.pending, (state) => {
        state.isLoading = true
        state.error = null
      })
      .addCase(getNewsInitial.fulfilled, (state, action) => {
        state.isLoading = false
        state.isLoaded = true // 请求成功后标记为已加载
        state.list = action.payload
      })
      .addCase(getNewsInitial.rejected, (state, action) => {
        state.isLoading = false
        state.error = action.error.message
      })
  }
})

export default newsSlice.reducer

之后修改组件的useEffect逻辑,请求前先判断状态,避免重复触发:

import { useSelector, useDispatch } from 'react-redux'

const NewsPage = () => {
  const dispatch = useDispatch()
  const { isLoaded, isLoading } = useSelector(state => state.news)
  const page = 1 // 或者从路由参数/其他地方获取

  useEffect(() => {
    // 只有数据未加载、且不在请求中的时候才发起请求
    if (!isLoaded && !isLoading) {
      dispatch(getNewsInitial(page))
    }
  }, [page, dispatch, isLoaded, isLoading])

  // 其余组件逻辑...
}

如果是分页场景,可以把isLoaded换成按页码存储的对象loadedPages,实现多页数据的缓存判断:

// initialState中修改
const initialState = {
  list: [],
  isLoading: false,
  loadedPages: {}, // 键为页码,值为是否已加载
  error: null
}

// fulfilled回调中修改
.addCase(getNewsInitial.fulfilled, (state, action) => {
  const currentPage = action.meta.arg // 即传入thunk的page参数
  state.isLoading = false
  state.loadedPages[currentPage] = true
  state.list = action.payload
})

// 组件useEffect中判断
useEffect(() => {
  if (!news.loadedPages[page] && !news.isLoading) {
    dispatch(getNewsInitial(page))
  }
}, [page, dispatch, news.loadedPages, news.isLoading])

方案2:使用RTK Query(更推荐的RTK原生方案)

如果后续可以调整技术方案,Redux Toolkit自带的RTK Query已经内置了请求去重、缓存、自动刷新、错误重试等能力,不需要你手动维护isLoaded这类状态,请求配置好之后默认就会避免重复发起相同参数的请求,还可以自定义缓存有效期、是否需要强制刷新等规则,更适合中大型项目的数据请求管理。

如果有强制刷新的需求(比如用户手动下拉刷新),只需要在触发请求的时候忽略isLoaded的判断即可,不会影响正常的缓存逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:24:02