admin管理员组文章数量:1123711
My infinite scroll component for my images works swimmingly on a normal page, but the second I put it in the MUI Dialog it fails to trigger any response on scroll. I have tried some ref tricks and intersection observer changes as well but to no avail. Any help is appreciated!
Infinite Scroll Component
import React, { useRef, useCallback, useEffect, useState, Fragment, useId } from 'react';
import { useParams } from '@remix-run/react';
import { useInfiniteQuery } from 'react-query';
import { getImagesPage } from '../../../services/media.service';
import { Box, Typography, Paper, useMediaQuery, Skeleton, ImageList, ImageListItem, useTheme } from '@mui/material';
import FileUpload from '../../../utils/Buttons/FileUpload';
import { CameraAltOutlined } from '@mui/icons-material';
interface ImageScrollProps {
listing: any;
type: any;
navigation: any;
initialData?: any;
};
const ImageScroll: React.FC<ImageScrollProps> = ({ listing, type, navigation, initialData }) => {
const { Id } = useParams<{ Id: string }>();
const newId = useId();
const theme = useTheme();
const extraSmall = useMediaQuery(theme.breakpoints.only('xs'));
const small = useMediaQuery(theme.breakpoints.only('sm'));
const columns = extraSmall ? 2 : (small ? 3 : 4);
const [imageCount, setImageCount] = useState<number>(0);
const width = (extraSmall || small) ? 300 : 410;
const [isLoading, setIsLoading] = useState(true);
const [containerHeight, setContainerHeight] = useState('19em');
const {
fetchNextPage,
hasNextPage,
isFetchingNextPage,
data,
status,
error
} = useInfiniteQuery<any, any>(`/${Id}`, ({ pageParam = 1 }) => getImagesPage(Id, pageParam, type), {
getNextPageParam: (lastPage: any, allPages: any) => {
if (lastPage && lastPage.length > 0) {
return allPages.length + 1;
}
return undefined;
},
// getNextPageParam: (lastPage: any, allPages: any) => {
// const nextPageNumber = allPages.length + 1;
// return lastPage.length ? nextPageNumber : undefined;
// },
initialData: initialData ? {
pages: [initialData],
pageParams: [1],
} : undefined,
onSettled: () => setIsLoading(false),
});
const allImages = data ? data.pages.flat() : [];
useEffect(() => {
if (data) {
setImageCount(prevCount => prevCount + data.pages.flat().length);
}
}, [data]);
// useEffect(() => {
// if (imageCount <= 2) {
// setContainerHeight('9.5em');
// }
// }, []);
useEffect(() => {
return () => {
if (intObserver.current) intObserver.current.disconnect()
}
}, [])
// const containerHeight = imageCount <= 2 ? '9.5em' : '19em';
const masonryContainerStyles = {
height: '100vh',
overflowY: 'auto',
width: '100%',
padding: '0em',
borderRadius: '15px',
'::WebkitScrollbar':
{ display: 'none' },
msOverflowStyle: 'none',
scrollbarWidth: 'none',
};
const intObserver = useRef();
const lastImageRef = useCallback(image => {
if (isFetchingNextPage) return;
if (intObserver.current) intObserver.current.disconnect();
intObserver.current = new IntersectionObserver(entries => {
if (entries[0].isIntersecting && hasNextPage) {
fetchNextPage();
}
}, { rootMargin: '200px' }); // Adjust this value as needed
if (image) intObserver.current.observe(image);
}, [isFetchingNextPage, fetchNextPage, hasNextPage]);
if (isLoading) {
return (
<Box style={masonryContainerStyles} sx={{ display: 'flex', justifyContent: 'center' }}>
<ImageList cols={2} gap={0} spacing={0} id='image-list'>
{[...Array(8)].map((_, index) => (
<Skeleton
key={`skeleton-${index + 1}`}
variant="rounded"
animation="wave"
width={180}
height={118}
/>
))}
</ImageList>
</Box>
);
}
const borderRadiusValue = '20px';
const content = (
<Box style={masonryContainerStyles} key={newId}>
<ImageList variant='masonry' cols={columns} spacing={0} gap={0} id='image list'>
{allImages.map((image, i) => {
const isLastImage = i === allImages.length - 1;
const uniqueKey = `${image._id}-${i}`;
const imageWidth = Math.round(parseInt(image.width, 10) * 1);
const imageHeight = Math.round(parseInt(image.height, 10) * 1);
const mediaElement = image.mediaType === 'video' ? (
<Box style={{ width: '100%', height: '100%', padding: 0, margin: 0, overflow: 'hidden' }} key={newId}>
<video
src={image.url}
aria-label='Video card'
id='video'
style={{
maxWidth: "100%",
maxHeight: "auto",
objectFit: "cover",
padding: 0,
margin: 0,
borderRadius: borderRadiusValue
}}
autoPlay
muted
loop
playsInline
/>
</Box>
) : (
<ImageListItem id={`image number ${uniqueKey}`} key={`image number - ${image._id}`}>
<img
src={image.url ?? ''}
alt={image.alt ? image.alt : `${listing.name} image`}
id={`image ${uniqueKey}`}
aria-label='Image card'
width={imageWidth}
height={imageHeight}
loading='eager'
style={{
objectFit: "cover",
padding: 0,
margin: 0,
display: 'block',
borderRadius: borderRadiusValue,
}}
/>
</ImageListItem>
);
return (
<>
{/* {status === 'success' &&
<Fragment> */}
<div ref={isLastImage ? lastImageRef : null} width={width}>
{mediaElement}
</div>
{/* </Fragment>
} */}
</>
);
})}
</ImageList>
</Box>
);
return (
<>
{status === 'error' && <p className='center'>Error: {error.message}</p>}
{status === 'success' && (
data?.pages && data.pages.flat().length > 0 ? content : (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Paper sx={{ display: 'flex', width: '80%', minHeight: '10.5em', justifyContent: 'center', alignItems: 'center', flexDirection: 'column', maxHeight: '300px', '::WebkitScrollbar': { display: 'none' }, overflow: 'auto', backgroundColor: '#F1F0E9', }}>
{
(small || extraSmall) ? (
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<CameraAltOutlined size={'xl'} />
<Typography variant="h6">
Nothing yet, add something!
</Typography>
</Box>
) : (
<Box sx={{ width: '50%', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<CameraAltOutlined size={'xl'} />
<Typography variant="h6">
Nothing yet, be the first to add something!
</Typography>
</Box>
)
}
</Paper>
</Box>
)
)}
{
(!listing.media) &&
<Box sx={{ marginLeft: { xl: '10em', lg: '9.5em', md: '8em', sm: '5em', xs: '2.8em' }, marginTop: '0.5em' }}>
<FileUpload type={type} listingId={listing._id} navigation={navigation} aria-label='Upload media button' />
</Box>
}
{
(listing.media) &&
<Box sx={{ marginLeft: '1em', marginTop: '0.5em' }}>
<FileUpload type={type} listingId={listing._id} navigation={navigation} aria-label='Upload media button' />
</Box>
}
</>
);
}
export default React.memo(ImageScroll);
Dialog Below
import { Fragment, useState } from 'react';
import { SwipeableDrawer, CssBaseline, Button, Box, Typography, TextField, Divider, IconButton, Avatar, Dialog, DialogContent } from '@mui/material';
import loadable from '@loadable/component';
import { useUniversalDialogContext } from "~/services/Contexts/UniversalDialogContext";
import { Close } from '@mui/icons-material';
const ImageScroll = loadable(() => import('../InfiniteScroll/Images/ImageScroll'));
const Puller = () => (
<Box
sx={{
width: 30,
height: 6,
backgroundColor: 'gray',
borderRadius: 3,
position: 'absolute',
top: 8,
left: 'calc(50% - 15px)',
}}
/>
);
const ImageDialog = ({ listing, type, navigation, initialData }) => {
const { openImageScroll, setOpenImageScroll } = useUniversalDialogContext();
return (
<Dialog
fullScreen
open={openImageScroll}
onClose={() => setOpenImageScroll(false)}
PaperProps={{
sx: {
backgroundColor: 'background.paper',
overflow: 'hidden' // Prevent double scrollbars
}
}}
>
<Box sx={{
position: 'absolute',
right: 8,
top: 8,
zIndex: 1
}}>
<IconButton
edge="start"
color="inherit"
onClick={() => setOpenImageScroll(false)}
aria-label="close"
>
<Close />
</IconButton>
</Box>
<DialogContent sx={{
p: 0,
height: '100vh',
overflow: 'auto',
'&::-webkit-scrollbar': { display: 'none' },
msOverflowStyle: 'none',
scrollbarWidth: 'none'
}}>
<Box sx={{ pt: 6 }}> {/* Add padding top to account for close button */}
<ImageScroll
listing={listing}
type={type}
navigation={navigation}
initialData={initialData}
/>
</Box>
</DialogContent>
</Dialog>
);
};
export default ImageDialog;
I have tried changing intersection observer, ref, and a few other window things but nothing works. I tried changing from a swipable drawer to this dialog and that did not work either.
本文标签: reactjsReact Query Infinite Scroll does not work in an MUI DialogStack Overflow
版权声明:本文标题:reactjs - React Query Infinite Scroll does not work in an MUI Dialog - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736591347a1945082.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论