react-infinite-scroll-component与Material UI Grid无限滚动失效问题
问题描述
我在应用首页展示用户帖子,共有约45条模拟数据,使用react-infinite-scroll-component每次加载5条。但实际仅能显示10-15条,之后滚动组件停留在“Loading...”状态不再加载。我将Material UI的Grid作为InfiniteScroll的子组件,疑惑二者是否兼容?同时state的使用方式是否会影响该功能?
相关代码
获取更多数据的函数
const fetchMoreData = (e) => { e.preventDefault() if (numberOfPosts.length >= 45) { setHasMore(false) return; } setTimeout(() => { setNumberOfPosts(numberOfPosts.concat(Array.from({length: 5}))) }, 500) }
无限滚动组件代码
<InfiniteScroll dataLength={numberOfPosts.length} next={fetchMoreData} hasMore={hasMore} loader={<h4>Loading...</h4>} id='all-post-container' scrollThreshold={1} endMessage={<p style={{ textAlign: "center" }}> <b>Yay! You have seen it all</b> </p>} style={{position: 'absolute', top: '25%', left: '20%', backgroundColor: 'red', height: '72%', width: "54%", borderRadius: '30px'}}> <Grid container direction="column" justifyContent="center" alignItems="center" spacing={45} > {numberOfPosts.map(key => { return ( <Grid container item> <div id="post-container" style={{margin: '5%', position: 'absolute', width: '90%', height: '40%', backgroundColor: 'white', borderRadius: '30px', overflow: 'auto'}}> <Avatar src={<AvatarPicture/>} style={{position: 'absolute', left: '1%', top: '3%', height: '60px', width: '60px'}} size='lg'></Avatar> <p style={{position: 'absolute', left: '9%', top: '-5%', fontFamily: 'Outfit', fontStyle: 'normal', fontWeight: '500', fontSize: '20px', lineHeight: '25px', overflow: 'auto'}}>@{state.storage.username}</p> <p style={{position: 'absolute', left: '9%', top: '10%', fontFamily: 'Outfit', fontStyle: 'normal', fontWeight: '400', fontSize: '16px', lineHeight: '20px', color: '#6D7683'}}>{state.storage.location}</p> <p style={{position: 'absolute', left: '20%', top: '10%', fontFamily: 'Outfit', fontStyle: 'normal', fontWeight: '400', fontSize: '16px', lineHeight: '20px', color: '#2D87FF'}}>time</p> <div id="text-container" style={{position: 'absolute', top: '30%', left: '5%', backgroundColor: '#FFFBEE', height: '30%', width: '90%', borderRadius: '16px'}}></div> <TextField InputProps={{ startAdornment: ( <InputAdornment> <Avatar src={state.storage.profileImageURL} /> </InputAdornment> ), classes: { notchedOutline: 'notched-outline-border-radius' } }} maxRows={10} inputProps={{maxLength: 500}} multiline style={{position: 'absolute', left: '5%', top: '78%', width: '90%', background: '#F8FAFF', border: '1px solid #D9E1F9', borderRadius: '16px'}} placeholder='Write your comment'></TextField> <IconButton onClick={() => setLike(!like)} style={{ position: 'absolute', top: '60%', left: '5%'}} onMouseLeave={() => setMouseOver(false)} onMouseOver={() => setMouseOver(true)}>{like && mouseOver ? <HeartBrokenIcon style={{color: 'red'}}/> : like ? <FavoriteIcon style={{color: 'red'}} /> : <FavoriteBorderTwoToneIcon /> }</IconButton> <p style={{position: 'absolute', top: '59%', left: '9%'}}>likes</p> <IconButton onClick={() => setReply(!reply)} style={{ position: 'absolute', top: '60%', left: '13%'}}>{reply ? <MessageIcon color="primary"/> : <MessageOutlinedIcon/>}</IconButton> <p style={{position: 'absolute', top: '59%', left: '17%'}}>replies</p> <IconButton style={{ position: 'absolute', top: '60%', left: '23%'}}><IosShareOutlinedIcon /></IconButton> <p style={{position: 'absolute', top: '59%', left: '27%'}}>shares</p> </div> </Grid> )})} </Grid> </InfiniteScroll>
问题原因及修复方案
1. State更新的闭包陷阱
你在fetchMoreData里直接用numberOfPosts.concat更新state,这里存在闭包问题——每次调用函数时,numberOfPosts都是函数创建时的旧值,导致后续数据无法正确累加,到一定次数后就无法触发新的加载。
修复: 使用函数式更新获取最新的state值:
const fetchMoreData = (e) => { e.preventDefault() if (numberOfPosts.length >= 45) { setHasMore(false) return; } setTimeout(() => { // 用prevPosts拿到最新的状态 setNumberOfPosts(prevPosts => prevPosts.concat(Array.from({length: 5}))) }, 500) }
2. 绝对定位破坏布局高度计算
你的帖子容器#post-container使用了position: absolute,这会让Grid无法正确计算内容的实际高度,导致InfiniteScroll错误判断已经滚动到底部,停止触发加载。
修复:
- 移除
#post-container的position: absolute,改用margin、padding或Grid的spacing来控制元素间距 - 确保InfiniteScroll的容器内的子元素(Grid)能正常撑开容器高度,让滚动事件被正确检测
3. Material UI Grid与InfiniteScroll的兼容性
二者本身完全兼容,但你设置的spacing={45}值过大,加上子元素的绝对定位,会导致布局混乱,影响InfiniteScroll的滚动检测逻辑。
建议:
- 把Grid的
spacing调整为合理值(比如2、3) - 避免子元素使用绝对定位破坏Grid的正常布局流
额外检查项
- 确认
hasMore的初始值为true - 调整
scrollThreshold为默认的0.8(设为1需要滚动到最底部才触发,容易出现检测延迟或失效)
内容的提问来源于stack exchange,提问作者SupraCoder
相关产品推荐
相关产品推荐

