React搭配Redux拉取图片存入state分片后出现严重性能损耗如何解决
问题原因与修复方案
核心代码错误
你当前的Redux Slice代码存在最直接的逻辑缺陷:fetchGames.fulfilled 回调中,完成结果解析得到parsedResults后,没有更新Redux的state状态。
两种最可能的实际场景对应卡顿原因:
- 你漏写了状态赋值代码,实际运行的版本中错误使用了
state.results.push(...parsedResults)这类追加逻辑,导致每次搜索的结果都叠加到同一份数组中,数组体积随搜索次数不断膨胀,渲染压力陡增,几次搜索后就会因为内存占用过高、渲染耗时过长导致页面无响应。 - 你没有处理并发请求,用户连续多次搜索时,之前未完成的请求全部保留,所有请求返回后都会触发状态更新和页面重渲染,多次无效渲染叠加后引发卡顿。
逐步修复方案
1. 修正Reducer状态更新逻辑
按照你“新结果替换旧结果”的需求,直接将解析后的结果赋值给state的results字段即可:
[fetchGames.fulfilled]: (state, action) => { const results = action.payload; const parsedResults = results.map((result) => { return { name: result.name, slug: result.slug, backgroundImage: result.background_image, genres: result.genres.map((genre) => genre.name).join(', '), id: result.id, released: result.released ? `${result.released.split('-')[2]}.${result.released.split('-')[1]}.${result.released.split('-')[0]}` : null, }; }); // 新增这行核心赋值逻辑,用新结果完全替换旧结果 state.results = parsedResults; },
如果你之前用了追加逻辑,直接删掉追加代码改为上述赋值即可。
2. 优化请求逻辑,取消冗余请求
新增请求取消逻辑,每次发起新搜索时自动中断上一次未完成的搜索请求,避免无效请求返回后触发多余渲染:
// 存储上一次请求的终止控制器 let lastFetchAbortController = null; export const fetchGames = createAsyncThunk( 'gamesSearch/fetchGames', async (query, { signal }) => { // 终止上一次未完成的请求 if (lastFetchAbortController) { lastFetchAbortController.abort(); } lastFetchAbortController = new AbortController(); try { const response = await rawg.get('/games', { params: { search: query, }, // 绑定终止信号到请求上 signal: lastFetchAbortController.signal }); return response.data.results; } catch (err) { // 忽略主动取消的请求错误 if (err.name === 'AbortError') return []; throw err; } } );
3. 渲染层优化(可选,结果量较大时建议使用)
- 列表项的
key属性必须使用返回的唯一id字段,禁止使用数组索引作为key - 单次返回结果超过20条时,使用虚拟滚动组件仅渲染可视区域内的列表项,大幅降低渲染开销
- 用
React.memo包裹列表项组件,避免无关状态更新触发的不必要重渲染
内容的提问来源于stack exchange,提问作者Lucian Anghel
相关产品推荐
相关产品推荐

