React/Redux学习应用页面导航时图片重复问题求助
React/Redux 页面导航时图片重复加载的问题排查与解决
我之前也碰到过类似的问题,结合你给出的代码和描述,帮你梳理下可能的原因和解决思路:
首先,你的核心问题是每次返回页面都会重复拉取图片并追加到页面上,本质上应该是请求重复触发加上Reducer的状态处理逻辑导致的。
先排查请求触发的原因
- 打开浏览器的DevTools,切换到Network标签,每次导航到目标页面时,看看是不是都会发起新的Contentful API请求。如果是的话,说明你的组件每次挂载/渲染都在调用
fetchAsset方法。- 如果是类组件:检查是不是把请求放在了
componentDidUpdate或者没有条件判断的componentWillReceiveProps里,导致每次组件更新都触发请求;应该确保只在componentDidMount里执行一次,或者只有当依赖的id变化时才重新请求。 - 如果是函数组件:看看
useEffect的依赖数组是不是没设置对——比如依赖数组是空数组的话只会执行一次,但如果依赖了某个每次渲染都会变化的变量(比如没有用useCallback包裹的函数),就会导致每次渲染都触发请求。
- 如果是类组件:检查是不是把请求放在了
再看Reducer的状态处理
从你提到的EMPTY_ARRAY来看,你的Reducer状态应该是一个数组结构。如果处理FETCH_ASSET动作时,你写的是类似return [...state, action.payload]这种代码,那每次请求回来的图片数据都会被追加到数组里,自然页面上会显示越来越多的重复图片。
针对性的解决方案
根据你的需求,分两种情况处理:
情况1:只需要展示单张图片
那完全没必要用数组来存状态,直接用单个对象即可,收到新数据时直接替换旧状态:
import { FETCH_ASSET } from '../actions/index'; // 初始状态设为null或者空对象 const initialState = null; export default function assetReducer(state = initialState, action) { switch(action.type) { case FETCH_ASSET: // 直接替换为新的资产数据 return action.payload.data; default: return state; } }
情况2:需要维护多个资产,但要避免重复
如果确实需要存储多个资产,那在Reducer里要先检查当前状态中是否已经存在相同id的资产,不存在再追加:
import { FETCH_ASSET } from '../actions/index'; const initialState = []; export default function assetReducer(state = initialState, action) { switch(action.type) { case FETCH_ASSET: const newAsset = action.payload.data; // 通过Contentful资产的sys.id判断是否已存在 const assetExists = state.some(asset => asset.sys.id === newAsset.sys.id); if (!assetExists) { return [...state, newAsset]; } // 已存在则直接返回原状态,不做修改 return state; default: return state; } }
额外优化:控制组件渲染
如果组件存在不必要的重复渲染,也可能间接导致重复请求。可以给组件加上优化:
- 函数组件用
React.memo包裹,浅比较props变化时才重新渲染; - 类组件继承
PureComponent,或者手动实现shouldComponentUpdate方法。
内容的提问来源于stack exchange,提问作者Calum Baines
相关产品推荐
相关产品推荐

