I want to do something only in component is in viewport. It almost working, but I have a one problem with which I can not manage.
class Hello extends React.Component {
componentDidMount() {
console.log(this.isInViewPort()) // false for second element - last in viewport
if (this.isInViewPort()) {
console.log("I'm in viewport!");
}
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
isInViewPort = () => {
const element = this.refs[this.props.id];
const rect = element.getBoundingClientRect();
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
const result = rect.top <= windowHeight && rect.top + rect.height >= 0;
return result;
}
handleScroll = () => {
if (this.isInViewPort()) {
console.log("I'm in viewport!");
}
}
render() {
return (
<div className="example" ref={this.props.id} onClick={this.handleScroll} /> // onClick added for tests
);
}
}
class App extends React.Component {
render() {
return (
<Hello id={1} />
<Hello id={2} />
<Hello id={3} />
);
}
}
.example {
width: 400px;
height: 400px;
background-color: red;
}
When I loading the page, two elements are in viewport. First one - 100% in viewport and second one - maybe 15-20% in viewport.
For this example I have only one console.log, so this.isInViewPort() is true only for first element. It's wrong, cause two of them are visible.
When I touch the event scroll, Component immediately visible for method and make console log. When I do not touch a scroll, but click on second component (this is added for tests) method return true and i get console.log.
I want to make situation when every visible elements returned true by method.
It works when I do this:
componentDidMount() {
setTimeout(() => {
if (this.isInViewPort()) {
console.log("I'm in viewport!");
}, 0);
}
But for 100% this is not a good solution. It also do not work when i put this code after refactor to componentDidUpdate().
It's something with react lifecycles? I do not doing anything witch state, that's why it is not understandable to me.