提问人:Vishwa 提问时间:9/5/2023 最后编辑:James ZVishwa 更新时间:10/8/2023 访问量:69
FixedSizeGrid 未触发 react-window 的 InfiniteLoader 内的 loadmoreitems
FixedSizeGrid not triggering loadmoreitems inside the InfiniteLoader of react-window
问:
我是 react js 的新手,我希望使用 react-window 创建一个产品列表。在使用 Infiniteloader 执行 fixedsize 列表时,loadMoreItems 工作正常,我能够进行 API 调用并将新数据集附加到 productList。但是我希望每行使用 3 个产品进行网格视图,同时使用 InfinitLoader 中的 FixedSizeGrid 执行此操作,我无法在滚动列表时进行 API 调用。有没有解决方案或替代方法?
import React, { useEffect, useState } from "react";
import Image from 'next/image'
import { FixedSizeList as List, FixedSizeGrid as Grid } from 'react-window'
import InfiniteLoader from 'react-window-infinite-loader'
import Paper from '@mui/material/Paper';
import { styled } from '@mui/material/styles';
import axios from 'axios';
import { Box, Stack, Typography } from '@mui/material';
// Custom imports
import { poppinsBold } from '../../shared/appfonts';
// Variables used for infinite virtualized list
const PAGE_SIZE = 20;
const TOTAL_PRODUCTS = 1000;
const LOAD_THRESHOLD = 200;
const itemSize = 200; // Fixed item size for 3 items per row
const columnCount = 3; // Number of columns (items per row)
const ProductList = () => {
const [products, setProducts] = useState([]); // State to maintain product list data
const [isLoading, setIsLoading] = useState(false); // State to maintain loading state while fetching products from the server
const [currentPage, setCurrentPage] = useState(1); // State to maintain the current page record
// Custom Title MUI component for UI
const TitleTypography = styled(Typography)({
fontFamily: poppinsBold.style.fontFamily,
color: 'black',
});
// Custom Medium MUI component for UI
const MediumTypography = styled(Typography)({
fontFamily: poppinsBold.style.fontFamily,
color: 'black',
});
// Function used to fetch products from the server
const fetchProducts = async (pageNumber = currentPage) => {
setIsLoading(true);
try {
const response = await axios.get(
`http://localhost:5000/products?_page=${pageNumber}&_limit=${PAGE_SIZE}`
);
const newProducts = response.data;
setProducts([...products, ...newProducts]);
setCurrentPage(currentPage + 1);
} catch (error) {
console.error('Error fetching products:', error);
} finally {
setIsLoading(false);
}
};
// Function used to load more product items to the infinite list
const loadMoreItems = () => {
console.log('load more items called')
if (!isLoading) {
console.log("currentPage", currentPage);
if (products.length < TOTAL_PRODUCTS) {
fetchProducts(currentPage);
}
}
};
useEffect(() => {
fetchProducts();
}, []); // Fetch initial data
const renderItem = ({ columnIndex, rowIndex, style }) => {
const index = rowIndex * columnCount + columnIndex;
const product = products[index];
return (
<div style={style} key={product?.id}>
<Paper sx={{ m: 3 }} elevation={3}>
<Stack display={'flex'} direction={'row'}>
<Image
width={120}
height={150}
src={
'https://images.pexels.com/photos/10863290/pexels-photo-10863290.jpeg?auto=compress&cs=tinysrgb&w=600'
}
alt="Alternate image"
style={{ objectFit: 'fill' }}
/>
<Box
display={'flex'}
alignItems={'center'}
flexDirection={'column'}
justifyContent={'center'}
width={'100%'}
>
<TitleTypography>{product?.name}</TitleTypography>
<MediumTypography>${product?.price}</MediumTypography>
</Box>
</Stack>
</Paper>
</div>
);
};
return (
<Box>
<InfiniteLoader
isItemLoaded={() => isLoading}
itemCount={TOTAL_PRODUCTS}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<Grid
height={window.innerHeight}
width={window.innerWidth}
columnCount={columnCount}
columnWidth={window.innerWidth / columnCount}
rowCount={Math.ceil(products.length / columnCount)}
rowHeight={200}
onItemsRendered={onItemsRendered}
ref={ref}
>
{renderItem}
</Grid>
)}
</InfiniteLoader>
</Box>
)
}
export default ProductList;
答:
0赞
Nikhil Shrestha
10/8/2023
#1
onItemsRendered={onItemsRendered} 的默认示例存在错误
更改此道具为我解决了问题。onItemsRendered={gridProps => { onItemsRendered({ overscanStartIndex: gridProps.overscanRowStartIndex * NUM_COLUMNS, overscanStopIndex: gridProps.overscanRowStopIndex * NUM_COLUMNS, visibleStartIndex: gridProps.visibleRowStartIndex * NUM_COLUMNS, visibleStopIndex: gridProps.visibleRowStopIndex * NUM_COLUMNS }); }}
import { FixedSizeGrid as Grid } from "react-window";
import InfiniteLoader from "react-window-infinite-loader";
const LOADING = 1;
const LOADED = 2;
const NUM_COLUMNS = 3;
let itemStatusMap = {};
const isItemLoaded = index => !!itemStatusMap[index];
const loadMoreItems = (startIndex, stopIndex) => {
for (let index = startIndex; index <= stopIndex; index++) {
itemStatusMap[index] = LOADING;
}
return new Promise(resolve =>
setTimeout(() => {
for (let index = startIndex; index <= stopIndex; index++) {
itemStatusMap[index] = LOADED;
}
resolve();
}, 2500)
);
};
class Cell extends PureComponent {
render() {
const { columnIndex, rowIndex, style } = this.props;
let label;
const itemIndex = rowIndex * NUM_COLUMNS + columnIndex;
if (itemStatusMap[itemIndex] === LOADED) {
label = `Cell (${rowIndex}, ${columnIndex})`;
} else {
label = "Loading...";
}
return (
<div className="ListItem" style={style}>
{label}
</div>
);
}
}
export default function App() {
return (
<Fragment>
<p className="Note">
This demo app mimics loading remote data with a 2.5s timer. While rows
are "loading" they will display a "Loading..." label. Once data has been
"loaded" the row number will be displayed. Start scrolling the list to
automatically load data.
</p>
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={1000}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<Grid
className="List"
columnCount={NUM_COLUMNS}
columnWidth={100}
height={150}
rowCount={1000}
rowHeight={35}
onItemsRendered={gridProps => {
onItemsRendered({
overscanStartIndex:
gridProps.overscanRowStartIndex * NUM_COLUMNS,
overscanStopIndex: gridProps.overscanRowStopIndex * NUM_COLUMNS,
visibleStartIndex: gridProps.visibleRowStartIndex * NUM_COLUMNS,
visibleStopIndex: gridProps.visibleRowStopIndex * NUM_COLUMNS
});
}}
ref={ref}
width={300}
>
{Cell}
</Grid>
)}
</InfiniteLoader>
<p className="Note">
Check out the documentation to learn more:
<br />
<a href="https://github.com/bvaughn/react-window-infinite-loader#documentation">
github.com/bvaughn/react-window-infinite-loader
</a>
</p>
</Fragment>
);
}
评论