Next.js 13中react-window全屏滚动无限加载布局问题
解决Next.js 13中react-window无限滚动的滚动条与布局适配问题
核心问题分析
你当前的代码存在两个关键问题:
- 直接使用
window.innerHeight作为列表高度,未扣除页眉和页脚的占用空间,导致列表被页脚遮挡或滚动条高度异常 - 绝对定位的容器破坏了根布局的flex流,无法与全局页眉、页脚正确共存
解决方案代码
组件修改(Wrapper.js)
import { useState, useEffect, useRef } from 'react'; import { InfiniteLoader, FixedSizeList } from 'react-window'; import styles from './Wrapper.module.css'; function Wrapper({ hasNextPage, isNextPageLoading, items, loadNextPage }) { const itemCount = hasNextPage ? items.length + 1 : items.length; const loadMoreItems = isNextPageLoading ? () => {} : loadNextPage; const isItemLoaded = (index) => !hasNextPage || index < items.length; const containerRef = useRef(null); const [listHeight, setListHeight] = useState(0); // 计算容器可用高度(自动扣除页眉页脚) useEffect(() => { const updateHeight = () => { if (containerRef.current) { setListHeight(containerRef.current.clientHeight); } }; updateHeight(); window.addEventListener('resize', updateHeight); return () => window.removeEventListener('resize', updateHeight); }, []); const Item = ({ index }) => { const content = !isItemLoaded(index) ? "Loading..." : items[index].name.first; return <div className={styles.item}>{content}</div>; }; return ( <div ref={containerRef} className={styles.scrollContainer}> <InfiniteLoader isItemLoaded={isItemLoaded} itemCount={itemCount} loadMoreItems={loadMoreItems} > {({ onItemsRendered, ref }) => ( <FixedSizeList itemCount={itemCount} onItemsRendered={onItemsRendered} ref={ref} height={listHeight} width="100%" itemSize={35} style={{ overflowY: 'auto' }} > {Item} </FixedSizeList> )} </InfiniteLoader> </div> ); } export default Wrapper;
CSS修改(Wrapper.module.css)
/* 滚动容器:由根布局flex分配剩余高度 */ .scrollContainer { flex: 1; width: 100%; overflow: hidden; } /* 新闻条目:限制最大宽度并居中 */ .item { max-width: 1920px; margin: 0 auto; padding: 8px 16px; border-bottom: 1px solid #eee; } /* 让滚动条和浏览器默认样式一致 */ .scrollContainer ::-webkit-scrollbar { width: 8px; } .scrollContainer ::-webkit-scrollbar-track { background: #f1f1f1; } .scrollContainer ::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; } .scrollContainer ::-webkit-scrollbar-thumb:hover { background: #555; }
根布局配置(app/layout.js)
确保根布局用flex垂直分布,让内容区占剩余高度:
import './globals.css'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body className={styles.pageContainer}> {/* 全局页眉 */} <header className={styles.header}>导航栏</header> {/* 内容区:由Wrapper组件填充 */} <main className={styles.main}>{children}</main> {/* 全局页脚 */} <footer className={styles.footer}>页脚</footer> </body> </html> ); }
对应的全局CSS(app/globals.css):
.pageContainer { display: flex; flex-direction: column; min-height: 100vh; margin: 0; padding: 0; } .header { height: 60px; /* 替换为实际页眉高度 */ background: #fff; border-bottom: 1px solid #eee; } .main { flex: 1; width: 100%; } .footer { height: 80px; /* 替换为实际页脚高度 */ background: #f5f5f5; border-top: 1px solid #eee; }
关键说明
- 高度适配:通过
containerRef获取父容器的可用高度,自动扣除页眉页脚的固定高度,同时监听窗口大小变化实时更新 - 布局兼容:根布局用flex垂直分布,内容区占剩余空间,避免绝对定位破坏原有布局流
- 滚动条统一:通过CSS伪类自定义滚动条样式,和浏览器默认样式保持一致,固定在页面右侧
- 宽度控制:新闻条目设置
max-width:1920px并居中,超出窗口宽度时两侧自动显示空白,符合需求
内容的提问来源于stack exchange,提问作者Caffeine
相关产品推荐
相关产品推荐

