基于水平滚动位置的回调函数问题

horizontal scroll position based callback function issue

提问人:Vishwa 提问时间:9/1/2023 最后编辑:Vishwa 更新时间:9/1/2023 访问量:28

问:

我是下一个新手,目前我正在尝试使用 react-window 实现一个水平产品列表来维护虚拟化。我希望在滚动时进行 api 调用并将新数据集附加到产品列表中。我已经使用虚拟化列表的 onscroll 进行了回调,但问题是 clientwidth 和 scrollwidth 始终保持不变,并且回调甚至没有达到我提到的阈值的末尾就完成了,而且 scrollleft 值始终保持 0。在这一点上,我感到震惊。提前感谢您的帮助。

这是代码

import Image from 'next/image';
import { VariableSizeList as List } from 'react-window'; // Import VariableSizeList
import Grid from '@mui/material/Grid';
import Paper from '@mui/material/Paper';
import Skeleton from '@mui/material/Skeleton';
import { styled } from '@mui/material/styles';
import axios from 'axios';
import { Box, Stack, Typography } from '@mui/material';

import { poppinsBold } from '../../shared/appfonts';

const PAGE_SIZE = 20;
const TOTAL_PRODUCTS = 1000;
const LOAD_THRESHOLD = 200;

const HorizontalProductList = () => {
    const [products, setProducts] = useState([]);
    const [isLoading, setIsLoading] = useState(false);
    const [currentPage, setCurrentPage] = useState(1);
    const containerRef = useRef();

    const itemSize = (index) => 300; // Fixed width of each item in pixels

    const TitleTypography = styled(Typography)({
        fontFamily: poppinsBold.style.fontFamily,
        color: 'black',
    });

    const MediumTypography = styled(Typography)({
        fontFamily: poppinsBold.style.fontFamily,
        color: 'black',
    });

    const fetchProducts = async () => {
        setIsLoading(true);
        try {
            const response = await axios.get(
                `http://localhost:5000/products?_page=${currentPage}&_limit=${PAGE_SIZE}`
            );
            const newProducts = response.data;
            setProducts([...products, ...newProducts]);
            setCurrentPage(currentPage + 1);
        } catch (error) {
            console.error('Error fetching products:', error);
        } finally {
            setIsLoading(false);
        }
    };

    useEffect(() => {
        fetchProducts();
    }, []); // Fetch initial data

    const handleScroll = useCallback(() => {
        if (!isLoading && containerRef.current) {
            const container = containerRef.current;
            const isNearEnd =
                container.scrollLeft + container.clientWidth + LOAD_THRESHOLD > container.scrollWidth;
            console.log("container.scrollLeft", container.scrollLeft);
            console.log("container.clientWidth", container.clientWidth);
            console.log("container.scrollWidth", container.scrollWidth);
            console.log("isNearEnd", isNearEnd);
            if (false) {
                fetchProducts();
            }
        }
    }, [isLoading]);

    const renderSkeletonItem = () => {
        return (
            <div>
                <Grid item xs={1} md={2} lg={3}>
                    <Paper>
                        <Skeleton variant="rectangular" width={300} height={200} />
                        <Skeleton variant="text" width={200} />
                        <Skeleton variant="text" width={150} />
                        <Skeleton variant="text" width={80} />
                    </Paper>
                </Grid>
            </div>
        );
    };

    const renderItem = ({ index, style }) => {
        // console.log("index", products[index])
        const product = products[index];

        if (!product) {
            // Render a skeleton loader for items that are being fetched
            return renderSkeletonItem();
        }

        return (
            <div style={style} key={product.id}>
                <Grid item xs={1} md={2} lg={3}>
                    <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>
                </Grid>
            </div>
        );
    };

    return (
        <div
            className="scroll-container" // Add a CSS class for horizontal scrolling
            ref={containerRef}
        >
            <div style={{ display: 'flex', overflowX: 'auto' }}>
                <List
                    height={200} // Specify the height of the list
                    width={typeof window !== 'undefined' ? window.innerWidth : 0} // Check for window object
                    itemCount={products.length + PAGE_SIZE} // Use products.length + PAGE_SIZE
                    itemSize={itemSize} // Width of each item
                    layout="horizontal" // Specify horizontal layout
                    onScroll={handleScroll}
                >
                    {renderItem}
                </List>
            </div>
        </div>
    );
};

export default HorizontalProductList;

这是上述代码的控制台映像clientwidth and scrollwidth equals image

ReactJS 用户界面 下一个 .js 虚拟化 React-Window

评论


答: 暂无答案