Skip to content

Instantly share code, notes, and snippets.

@mauricedb
Last active May 6, 2018 19:10
Show Gist options
  • Save mauricedb/e24bdb1fd6313e3bed8781a4babc3e48 to your computer and use it in GitHub Desktop.
Save mauricedb/e24bdb1fd6313e3bed8781a4babc3e48 to your computer and use it in GitHub Desktop.
Only render visible images
import { h, Component } from "preact";
import { Link } from "preact-router";
import style from "./style";
export default class Movie extends Component {
element = null;
componentDidMount() {
this.props.observer.observe(this.element);
}
componentWillUnmount() {
this.props.observer.unobserve(this.element);
}
render({ movie }) {
return (
<div
class={["card", style.movieCard].join(" ")}
ref={el => (this.element = el)}
data-id={movie.id}
>
<img
class="card-img-top"
src={
movie.isVisible
? movie.image
: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8Xw8AAoMBgDTD2qgAAAAASUVORK5CYII="
}
alt="Card image cap"
height="140"
/>
<div class="card-body">
<h4 class="card-title">{movie.title}</h4>
<Link href={`/movie/${movie.id}`}>Edit</Link>
<p class="card-text">{movie.overview}</p>
</div>
<div class="card-footer text-cente">
{movie.genres.map(genre => (
<span
class={[
"badge",
"badge-pill",
"badge-info",
style.genreBadge
].join(" ")}
>
{genre}
</span>
))}
</div>
</div>
);
}
}
import { h, Component } from 'preact';
import MoviesObserver from './movies-observer';
export default class MoviesContainer extends Component {
state = {
movies: []
};
componentDidMount() {
fetch("/api/movies.json")
.then(rsp => rsp.json())
.then(movies => this.setState({ movies }));
}
render({}, { movies }) {
return <MoviesObserver movies={movies} />;
}
}
import { h, Component } from 'preact';
import MoviesPresentation from './movies-presentation';
export default class MoviesObserver extends Component {
constructor() {
super();
this.observer = new IntersectionObserver(this.onIntersection);
this.observer.POLL_INTERVAL = 100; // Time in milliseconds for the polyfill.
}
onIntersection = entries => {
const { movies } = this.props;
entries.forEach(entry => {
const id = +entry.target.dataset.id;
const movie = movies.find(m => m.id === id);
if (movie) {
movie.isVisible = movie.isVisible || entry.isIntersecting;
}
});
this.forceUpdate();
};
render({ movies }) {
return <MoviesPresentation movies={movies} observer={this.observer} />;
}
}
import { h, Component } from "preact";
import style from "./style";
import Movie from "../../components/movie";
export default ({ movies, observer }) => (
<div class={style.movies}>
<h2>Movies</h2>
<div class="card-deck">
{movies.map(movie => <Movie movie={movie} observer={observer} />)}
</div>
</div>
);
npm install intersection-observer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment