react-infinite-scroll-component仅触发一次 无法加载更多VideoThumbnail组件
问题解决方案
核心原因
你遇到的内容替换而非追加的问题,本质是Redux Reducer处理HOME_VIDEOS_SUCCESS时直接覆盖了原视频数组,没有做新旧数据拼接,其次存在无限滚动组件配置不完善的问题。
具体修复步骤
1. 修正Redux Reducer逻辑
找到你对应homeVideos的reducer文件,修改HOME_VIDEOS_SUCCESS的处理逻辑,将新返回的视频列表拼接到原有列表末尾,示例代码如下:
const initialState = { videos: [], nextPageToken: null, loading: false, error: null } export const homeVideosReducer = (state = initialState, action) => { switch (action.type) { case HOME_VIDEOS_REQUEST: return { ...state, loading: true } case HOME_VIDEOS_SUCCESS: return { ...state, loading: false, // 核心修改:拼接新旧视频数组,而不是直接覆盖 videos: [...state.videos, ...action.payload.videos], nextPageToken: action.payload.nextPageToken } case HOME_VIDEOS_FAIL: return { ...state, loading: false, error: action.payload } default: return state } }
2. 完善无限滚动组件配置
你当前的InfiniteScroll组件hasMore写死为true,会导致没有更多数据时仍重复发送请求,需要从Redux中读取nextPageToken做判断,同时可以添加加载提示提升体验,修改组件代码如下:
const TrendingPage = () => { const dispatch = useDispatch(); // 同时取出nextPageToken和loading状态 const { videos, nextPageToken, loading } = useSelector((state) => state.homeVideos); const fetchData = () => { // 非加载状态下才发请求,避免重复触发 if (!loading) { dispatch(getPopularVideos()); } }; useEffect(() => { dispatch(getPopularVideos()); }, [dispatch]); return ( <div className="page-container wrap-content"> <InfiniteScroll dataLength={videos.length} next={fetchData} // 存在下一页token时才允许加载更多 hasMore={!!nextPageToken} // 加载时显示的提示内容 loader={<h4>加载中...</h4>} > {videos.map((item) => ( <VideoThumbnail key={item.id} image={item.snippet.thumbnails.medium.url} time={moment .utc( moment.duration(item.contentDetails.duration).asSeconds() * 1000 ) .format("mm:ss")} owner={item.snippet.channelTitle} name={item.snippet.title} minWidth="230px" /> ))} </InfiniteScroll> </div> ); };
可选优化
你的getPopularVideosaction逻辑本身没有问题,可添加没有nextPageToken时不发送请求的判断,减少无效请求:
export const getPopularVideos = () => async (dispatch, getState) => { try { // 没有下一页token且已有视频数据时直接终止,避免无效请求 if (!getState().homeVideos.nextPageToken && getState().homeVideos.videos.length > 0) return; dispatch({ type: HOME_VIDEOS_REQUEST, }); const { data } = await request.get("/videos", { params: { part: "snippet, contentDetails, statistics", chart: "mostPopular", regionCode: "TR", maxResults: 20, pageToken: getState().homeVideos.nextPageToken, }, }); dispatch({ type: HOME_VIDEOS_SUCCESS, payload: { videos: data.items, nextPageToken: data.nextPageToken, }, }); } catch (error) { console.log(error); dispatch({ type: HOME_VIDEOS_FAIL, payload: error.message, }); } };
内容的提问来源于stack exchange,提问作者Ziya Arslan
相关产品推荐
相关产品推荐

