如何避免重新进入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
相关产品推荐
相关产品推荐

