It took me a while to figure out how to lazy load images using the excellent React Lazyload component.
The demo lazy loaded images on scroll but when testing I could not get the same behavior.
The culprit was overflow: auto;
which conflicted with the component working as intended.
What is the best way to lazy load large image gallery/slideshows in React?
React Lazyload (Really liking this component but want to investigate others)
React Virtualized (Seems heavy but feature-rich)
React Infinite (Higher barrier to entry due to complexity)
React Lazylist (Straight-forward but not sure if optimal for images)
Others...?
I have a universal/isomorphic application so some of the above will break due to window object unable to be used on the server.
Infinite scroll uses lazy loading and executes its demand to load more data (products or content) at the bottom of the page, without requiring an action such as the click of a button. On-demand loading is used to optimize content delivery by reducing time consumption and memory usage.
The major benefit of lazy loading in React is performance. Loading less JavaScript code to the browser will reduce DOM load time and boost the performance of our application. Users are able to access a web page even if everything has not been loaded.
import React from "react"; import { lazyLoader } from "./lazyLoader"; const Customer = lazyLoader(() => import("./Customer. js")); const Admin = lazyLoader(() => import("./Admin. js")); //Instead of regular import statements, we will use the above approach for lazy loading export default (props) => { if (props.
If you want a simpler lazy load solution and not have to use other people's packages/code, try using the IntersectionObserver
API.
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
I wrote a Medium article on how to use it to lazy load images in a React component (implementation is essentially the same with vanilla JS).
https://medium.com/@parkjoon94/lazy-loading-images-intersectionobserver-8c5bff730920
You only really need this part of the code (snippet from above article):
this.observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
const { isIntersecting } = entry;
if (isIntersecting) {
this.element.src = this.props.src;
this.observer = this.observer.disconnect();
}
});
}, {}
);
import React from "react";
import PropTypes from "prop-types";
import axios from "axios";
import InfiniteScroll from "react-infinite-scroller";
const styles = theme => ({
root: {
textAlign: "center",
paddingTop: theme.spacing.unit * 20
}
});
class Parent extends React.Component {
state = {
allposts: [],
posts: [],
hasMore: true,
curpage: 0,
pagesize: 30,
totalPage: 0,
total: 0
};
componentDidMount() {
axios.get("https://jsonplaceholder.typicode.com/posts").then(res => {
let curpage = this.state.curpage;
let posts = res.data.slice(
curpage * this.state.pagesize,
(curpage + 1) * this.state.pagesize
);
this.setState({
allposts: res.data,
posts: posts,
total: res.data.length,
totalPage: Math.ceil(res.data.length / this.state.pagesize)
});
});
}
loadmoreItem() {
if (this.state.curpage + 1 < this.state.totalPage) {
let curpage =
this.state.curpage < this.state.totalPage
? this.state.curpage + 1
: this.state.curpage;
let posts = this.state.allposts.slice(
0,
(curpage + 1) * this.state.pagesize
);
this.setState({ posts: posts, curpage });
} else {
this.setState({ hasMore: false });
}
}
render() {
if (this.state.posts.length === 0) return <h1>loading...</h1>;
else {
console.log(this.state);
return (
<div>
<Table
hasMore={this.state.hasMore}
posts={this.state.posts}
loadmoreItem={this.loadmoreItem.bind(this)}
/>
</div>
);
}
}
}
export default Parent;
const Table = props => {
console.log("props: ", props);
return (
<React.Fragment>
<div style={{ height: "400px", overflow: "auto" }}>
<InfiniteScroll
pageStart={0}
loadMore={props.loadmoreItem}
hasMore={props.hasMore}
loader={
<div className="loader" key={0}>
Loading ...
</div>
}
useWindow={false}
threshold={350}
>
<table>
<tr>
<th>id</th>
<th>title</th>
<th>body</th>
</tr>
{props.posts.map(item => {
return (
<tr>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.body}</td>
</tr>
);
})}
</table>
</InfiniteScroll>
</div>
<button onClick={props.loadmoreItem}>next</button>
</React.Fragment>
);
};
check live example here
https://codesandbox.io/s/x228lmm90q
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With