reactjs - React lazy load won't work inside React perfect scroll bar
问题描述
I am using react-perfect-scrollbar to show images list. Inside the perfect scroll bar, I am going to lazy load images. But it won't work.
import React, { useState, useCallback, useEffect } from 'react';
import PerfectScrollbar from 'react-perfect-scrollbar';
import useIsMountedRef from 'src/hooks/useIsMountedRef';
import LazyLoad from 'react-lazyload';
import {
Box,
Button,
Link,
List,
ListItem,
ListItemIcon,
ListItemText,
CircularProgress,
Typography,
makeStyles
} from '@material-ui/core';
const isMountedRef = useIsMountedRef();
const [images, setImages] = useState([]);
const getImages = useCallback(async () => {
try {
setLoading(true);
const response = await axios.get(`${backendUrl}/images/get/images`);
if (isMountedRef.current) {
setImages(response.data.projectImages);
}
} catch (err) {
console.error(err);
} finally {
if (isMountedRef.current) {
setLoading(false);
}
}
}, [isMountedRef]);
<PerfectScrollbar options={{ suppressScrollX: true }}>
<List className={classes.list}>
{images.map((image, i) => (
<ListItem
divider={i < images.length - 1}
key={i}
className={classes.listItem}
>
<ListItemIcon>
<LazyLoad height={90} key={i} overflow>
<img
src={`${awsS3Url}/${image.Key}`}
className={classes.listImage}
onClick={() => onSelect(`${awsS3Url}/${image.Key}`)}
/>
</LazyLoad>
</ListItemIcon>
<ListItemText
primary={GetFilename(image.Key)}
primaryTypographyProps={{ variant: 'h5' }}
secondary={bytesToSize(image.Size)}
className={classes.listItemText}
/>
<MoreButton
handleArchive={() => handleRemoveOne(image)}
/>
</ListItem>
))}
</List>
</PerfectScrollbar>
Some of images(the first view without scrolling) are showing. When I scroll, the images won't load, only the list contents without images are showing.
What did I code wrong?
解决方案
我有同样的问题。问题是 react-lazyload 试图找到一个将其overflow
属性设置为scroll
or的容器auto
,但 perfect-scrollbar 将其overflow
属性设置为hidden
并手动处理滚动。所以我们必须手动告诉 react-lazyload 它应该监控哪个容器的scroll
事件。
这可以通过文档以两种方式完成;通过传递一个HTMLElement
或一个查询选择器字符串。唉,库中似乎存在一个错误,如果它不是字符串,则会导致该属性被忽略(https://github.com/twobin/react-lazyload/blob/055405125d0313014f0951cffc78345297f10a08/lib/index.js#L261 ) 所以目前唯一的方法是传递一个查询选择器字符串。
但是当我尝试传递一个针对完美滚动条容器的查询选择器字符串时,当 react-lazyload 附加其事件侦听器时,似乎容器可能并不总是存在,因此我们必须在初始化之前检查容器是否确实存在LazyLoad 容器。
所以相关代码是:
import React, { ReactElement, useRef, useState, useEffect } from 'react';
import PerfectScrollbar from 'react-perfect-scrollbar'
import LazyLoad from 'react-lazyload';
export default (): ReactElement => {
// Get a reference to the wrapper element so we know when it is created
const scrollbarWrapperRef = useRef(null);
// Initialize a state setter to notify the view when the scrollParent becomes available
const [scrollParent, setScrollParent] = useState<HTMLElement|null>(null);
// Adjust this selector to your liking
const scrollParentSelector = '#scrollbar-wrapper .scrollbar-container';
// Here we make sure that the PerfectScrollbar container is actually available before we let the content and the LazyLoads be created.
useEffect(() => {
const scrollParentElement = document.querySelector(scrollParentSelector);
if (scrollParentElement) {
setScrollParent(scrollParentElement);
}
}, [scrollbarWrapperRef.current]);
// The relevant DOM
return (
<div ref={scrollbarWrapperRef} id="scrollbar-wrapper">
<PerfectScrollbar>
{ scrollParent &&
<List>
{images.map((image, i) => (
<LazyLoad scrollContainer={scrollParentSelector}>
<img src="..." />
</LazyLoad>
))}
</List>
}
</PerfectScrollbar>
</div>
);
}
推荐阅读
- javascript - Office.js POST 方法被转换为 GET
- python - Alembic 降级、升级、修订和迁移无济于事
- clonezilla - 如何更改 Clonezilla 默认菜单选择项
- javascript - 为什么javascript`for`循环快速静音/取消静音视频
- php - Laravel 试图检索模型的 ID 但不工作?
- sql - 使用联合将不同的查询与不同的组连接起来
- javascript - 如何将使用在根组件中声明的 setState 的对象排序到不同的文件中?
- c# - 在控制器中添加后模型视图模型字典值 null
- c# - 与 C# 中的 Paint 方法相比,使用 OnPaint 覆盖方法有什么优势?
- javascript - 当我需要同时过滤多个东西时,如何调用过滤器一次?