我是react js的新手,我想用react窗口创建一个产品列表。在使用Infiniteloader执行固定大小列表时,loadMoreItems工作正常,我能够进行API调用并将新的数据集追加到productList。但是我希望每行有3个产品的gridview,同时使用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;
1条答案
按热度按时间roqulrg31#
onItemsRendered={onItemsRendered}的默认示例存在错误
把这个 prop 改成
onItemsRendered={gridProps => { onItemsRendered({ overscanStartIndex: gridProps.overscanRowStartIndex * NUM_COLUMNS, overscanStopIndex: gridProps.overscanRowStopIndex * NUM_COLUMNS, visibleStartIndex: gridProps.visibleRowStartIndex * NUM_COLUMNS, visibleStopIndex: gridProps.visibleRowStopIndex * NUM_COLUMNS }); }}
解决了我的问题。