Я пытаюсь создать компонент класса React, который ведет себя так же (и правильно), как и React Hook, который я разработал. Пример, который я привел в stackblitz и показан здесь, не показывает правильные изображения при первой загрузке страницы. Когда происходит событие прокрутки, оно становится правильным.
У меня есть следующий пример, который показывает неправильное поведение. Вы можете увидеть правильное поведение, изменив оператор импорта на тот, который в настоящее время закомментирован. Хук прерывается таким же образом, когда я удаляю isLoading из массива зависимостей useEffect.
https://stackblitz.com/edit/react-scroll-problem
ПРИМЕЧАНИЕ. Изменение isLoading на false в конструкторе решает проблему, но добавляет двойное отображение изображения (сначала черно-белое, затем цветное), которое не имеет зацепок.
import * as React from "react";
class ImageToggleOnScrollCC extends React.Component {
constructor(props) {
super(props);
this.imgRef = React.createRef();
this.state = {
inView: false,
isLoading: true
};
}
isInView = imageRefx => {
if (this.imgRef.current) {
const rect = this.imgRef.current.getBoundingClientRect();
return rect.top >= 0 && rect.bottom <= window.innerHeight;
}
return false;
};
scrollHandler = () => {
this.setState({
inView: this.isInView()
});
};
// componentDidUpdate(prevProps) {
// console.log("componentDidUpdate")
// if (this.props.isLoading !== prevProps.isLoading) {
// console.log("componentDidUpdate isLoading changed")
// }
// }
componentWillUnmount() {
window.removeEventListener("scroll", scrollHandler);
}
componentDidMount() {
window.addEventListener("scroll", this.scrollHandler);
this.setState({
inView: this.isInView(),
isLoading: false
});
}
render() {
if (this.state.isLoading === true) {
return null;
} else {
return (
<div>
<i>ImageToggleOnScrollCC - Class Component</i>
<br />
<img
src={
this.state.inView
? 'https://via.placeholder.com/200x200.png/0000FF/808080?text=ON-SCREEN'
: 'https://via.placeholder.com/200x200.png?text=off-screen'
}
alt=""
ref={this.imgRef}
width="200"
height="200"
/>
</div>
);
}
}
}
export default ImageToggleOnScrollCC;
Ниже приведен рабочий компонент React Hook, который я хочу, чтобы компонент Class выше работал так же, как.
import React, { useRef, useEffect, useState } from "react";
const ImageTogglerOnScroll = ({ primaryImg, secondaryImg }) => {
const imageRef = useRef(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
window.addEventListener("scroll", scrollHandler);
setInView(isInView());
setIsLoading(false);
return () => {
window.removeEventListener("scroll", scrollHandler);
};
}, [isLoading]);
const [inView, setInView] = useState(false);
const isInView = () => {
if (imageRef.current) {
const rect = imageRef.current.getBoundingClientRect();
return rect.top >= 0 && rect.bottom <= window.innerHeight;
}
return false;
};
const scrollHandler = () => {
setInView(() => {
return isInView();
});
};
return isLoading ? null : (
<div>
<i>ImageToggleOnScroll - Functional Component React Hooks</i>
<br />
<img
src={inView ? secondaryImg : primaryImg}
alt=""
ref={imageRef}
width="200"
height="200"
/>
</div>
);
};
export default ImageTogglerOnScroll;