英文:
useRef to detect isVisible is not working
问题
我正在尝试为我的React div添加滚动时的动画效果,当我滚动并到达该区域时,我希望它淡入显示,但问题是useEffect
用于检测滚动部分的部分不起作用,我不知道哪里出了问题。你们可以帮我解决这个问题吗?
这是代码:
我的useEffect
useEffect(() => {
const handleScroll = () => {
const element = aboutEncotekiRef.current;
console.log('element', element);
if (element) {
const { top, bottom } = element.getBoundingClientRect();
const isVisible = top < window.innerHeight && bottom >= 0;
setIsVisible(isVisible);
console.log('hello world');
}
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
我的div
<div className={`aboutEncoteki ${isVisible ? 'fade-in' : ''}`} ref={aboutEncotekiRef}>
<Row className='mb-3' lg={12} md={12} sm={12} xs={12}>
<h1 className='FontGothamRoundedBold'>
Try me
</h1>
</Row>
</div>
英文:
I'm trying to add animation to my react div when I scroll and reach the area. I want it to fade in, but the problem is the useEffect
to detect the scroll part is not working and I don't know what is wrong with it. Can you guys help me with this?
Here's the code:
My useEffect
useEffect(() => {
const handleScroll = () => {
const element = aboutEncotekiRef.current;
console.log('element', element);
if (element) {
const { top, bottom } = element.getBoundingClientRect();
const isVisible = top < window.innerHeight && bottom >= 0;
setIsVisible(isVisible);
console.log('hello world');
}
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
My div
<div className={`aboutEncoteki ${isVisible ? 'fade-in' : ''}`} ref={aboutEncotekiRef}>
<Row className='mb-3' lg={12} md={12} sm={12} xs={12}>
<h1 className = 'FontGothamRoundedBold'>
Try me
</h1>
</Row>
</div>
答案1
得分: 1
以下是您要翻译的内容:
更新的回答:
我一直在这里尝试您的代码:
看起来它正在按预期工作。
更新2:
如我们在聊天中讨论的建议,为了提高性能,您可以使用Intersection Observer API 和这段代码。
从调试中看来,似乎有一个包装器(父元素)围绕着具有滚动的元素,而不是窗口。
Intersection Observer API 的代码如下:
React.useEffect(() => {
const handleScroll = (entries) => {
const isVisible = entries[0].isIntersecting;
setIsVisible(isVisible);
};
const options = {
root: null, // 使用视口作为根
rootMargin: "0px",
threshold: 0.01, // 根据需要调整阈值
};
const observer = new IntersectionObserver(handleScroll, options);
const target = aboutEncotekiRef.current;
if (target) {
observer.observe(target);
}
return () => {
if (target) {
observer.unobserve(target);
}
};
}, []);
请注意,以上内容已经翻译完成,不包括代码部分。
英文:
<s>Just as @nuser137 mentioned, you should remove the dependency array. Your useEffect
executes only once.
See: https://css-tricks.com/run-useeffect-only-once/
</s>
Updated answer:
I have been playing with your code in here:
It looks like it is working as expected.
UPDATE 2:
As suggested in our discussion in the chat, for performance you can use the Intersection Observer API and this code.
From the debugging, seems like there's a wrapper (parent element) around your element that has the scroll and not the window.
Code for Interesection Observer API below:
React.useEffect(() => {
const handleScroll = (entries) => {
const isVisible = entries[0].isIntersecting;
setIsVisible(isVisible);
};
const options = {
root: null, // Use the viewport as the root
rootMargin: "0px",
threshold: 0.01, // Adjust the threshold as needed
};
const observer = new IntersectionObserver(handleScroll, options);
const target = aboutEncotekiRef.current;
if (target) {
observer.observe(target);
}
return () => {
if (target) {
observer.unobserve(target);
}
};
}, []);
答案2
得分: 0
Effects are triggered when the dependency array items changes, so you need to save the scrollTop in a state and add to the array dep of the effect, with this when scroll changes the effect is executed.
英文:
Effects are triggered when the dependency array items changes, so you need to save the scrollTop in a state and add to the array dep of the effect, with this when scroll changes the effect is executed
答案3
得分: 0
以下是翻译好的部分:
这是一个运行良好的示例。我不确定您遇到了什么确切的问题,但这个JS Fiddle可行。
https://jsfiddle.net/Bro3Simon/neuhq3ba/9/
function App() {
const [isVisible, setIsVisible] = React.useState(false);
const aboutEncotekiRef= React.useRef();
React.useEffect(() => {
const handleScroll = () => {
const element = aboutEncotekiRef.current;
if (element) {
const { top, bottom } = element.getBoundingClientRect();
const isVisible = top < window.innerHeight && bottom >= 0;
setIsVisible(isVisible);
}
};
console.log("I ran on first render only!");
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<>
<div style={{backgroundColor: isVisible ? "red" : "yellow", height: "200vh"}}>{`Is The Second Element Visible : ${isVisible}`}</div>
<div className={`aboutEncoteki ${isVisible ? 'fade-in' : ''}`} ref={aboutEncotekiRef} >
{`Is Element Visible : ${isVisible}`}
</div>
</>
);
}
英文:
Here is a working example that works fine. I am not sure what exact problem you were facing but this JS Fiddle works.
https://jsfiddle.net/Bro3Simon/neuhq3ba/9/
function App() {
const [isVisible, setIsVisible] = React.useState(false);
const aboutEncotekiRef= React.useRef();
React.useEffect(() => {
const handleScroll = () => {
const element = aboutEncotekiRef.current;
if (element) {
const { top, bottom } = element.getBoundingClientRect();
const isVisible = top < window.innerHeight && bottom >= 0;
setIsVisible(isVisible);
}
};
console.log("I ran on first render only!");
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<>
<div style={{backgroundColor: isVisible ? "red": "yellow", height: "200vh"}}>{`Is The Second Element Visible : ${isVisible}`}</div>
<div className={`aboutEncoteki ${isVisible ? 'fade-in' : ''}`} ref={aboutEncotekiRef} >
{`Is Element Visible : ${isVisible}`}
</div>
</>
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论