useRef 无法检测 isVisible 的工作情况。

huangapple go评论107阅读模式
英文:

useRef to detect isVisible is not working

问题

我正在尝试为我的React div添加滚动时的动画效果,当我滚动并到达该区域时,我希望它淡入显示,但问题是useEffect用于检测滚动部分的部分不起作用,我不知道哪里出了问题。你们可以帮我解决这个问题吗?

这是代码:

我的useEffect

  1. useEffect(() => {
  2. const handleScroll = () => {
  3. const element = aboutEncotekiRef.current;
  4. console.log('element', element);
  5. if (element) {
  6. const { top, bottom } = element.getBoundingClientRect();
  7. const isVisible = top < window.innerHeight && bottom >= 0;
  8. setIsVisible(isVisible);
  9. console.log('hello world');
  10. }
  11. };
  12. window.addEventListener('scroll', handleScroll);
  13. return () => {
  14. window.removeEventListener('scroll', handleScroll);
  15. };
  16. }, []);

我的div

  1. <div className={`aboutEncoteki ${isVisible ? 'fade-in' : ''}`} ref={aboutEncotekiRef}>
  2. <Row className='mb-3' lg={12} md={12} sm={12} xs={12}>
  3. <h1 className='FontGothamRoundedBold'>
  4. Try me
  5. </h1>
  6. </Row>
  7. </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

  1. useEffect(() =&gt; {
  2. const handleScroll = () =&gt; {
  3. const element = aboutEncotekiRef.current;
  4. console.log(&#39;element&#39;, element);
  5. if (element) {
  6. const { top, bottom } = element.getBoundingClientRect();
  7. const isVisible = top &lt; window.innerHeight &amp;&amp; bottom &gt;= 0;
  8. setIsVisible(isVisible);
  9. console.log(&#39;hello world&#39;);
  10. }
  11. };
  12. window.addEventListener(&#39;scroll&#39;, handleScroll);
  13. return () =&gt; {
  14. window.removeEventListener(&#39;scroll&#39;, handleScroll);
  15. };
  16. }, []);

My div

  1. &lt;div className={`aboutEncoteki ${isVisible ? &#39;fade-in&#39; : &#39;&#39;}`} ref={aboutEncotekiRef}&gt;
  2. &lt;Row className=&#39;mb-3&#39; lg={12} md={12} sm={12} xs={12}&gt;
  3. &lt;h1 className = &#39;FontGothamRoundedBold&#39;&gt;
  4. Try me
  5. &lt;/h1&gt;
  6. &lt;/Row&gt;
  7. &lt;/div&gt;

答案1

得分: 1

以下是您要翻译的内容:

更新的回答:

我一直在这里尝试您的代码:

CODEPEN

看起来它正在按预期工作。

更新2:
如我们在聊天中讨论的建议,为了提高性能,您可以使用Intersection Observer API 和这段代码。

从调试中看来,似乎有一个包装器(父元素)围绕着具有滚动的元素,而不是窗口。

Intersection Observer API 的代码如下:

  1. React.useEffect(() => {
  2. const handleScroll = (entries) => {
  3. const isVisible = entries[0].isIntersecting;
  4. setIsVisible(isVisible);
  5. };
  6. const options = {
  7. root: null, // 使用视口作为根
  8. rootMargin: "0px",
  9. threshold: 0.01, // 根据需要调整阈值
  10. };
  11. const observer = new IntersectionObserver(handleScroll, options);
  12. const target = aboutEncotekiRef.current;
  13. if (target) {
  14. observer.observe(target);
  15. }
  16. return () => {
  17. if (target) {
  18. observer.unobserve(target);
  19. }
  20. };
  21. }, []);

请注意,以上内容已经翻译完成,不包括代码部分。

英文:

<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:

CODEPEN

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:

  1. React.useEffect(() =&gt; {
  2. const handleScroll = (entries) =&gt; {
  3. const isVisible = entries[0].isIntersecting;
  4. setIsVisible(isVisible);
  5. };
  6. const options = {
  7. root: null, // Use the viewport as the root
  8. rootMargin: &quot;0px&quot;,
  9. threshold: 0.01, // Adjust the threshold as needed
  10. };
  11. const observer = new IntersectionObserver(handleScroll, options);
  12. const target = aboutEncotekiRef.current;
  13. if (target) {
  14. observer.observe(target);
  15. }
  16. return () =&gt; {
  17. if (target) {
  18. observer.unobserve(target);
  19. }
  20. };
  21. }, []);

答案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/

  1. function App() {
  2. const [isVisible, setIsVisible] = React.useState(false);
  3. const aboutEncotekiRef= React.useRef();
  4. React.useEffect(() => {
  5. const handleScroll = () => {
  6. const element = aboutEncotekiRef.current;
  7. if (element) {
  8. const { top, bottom } = element.getBoundingClientRect();
  9. const isVisible = top < window.innerHeight && bottom >= 0;
  10. setIsVisible(isVisible);
  11. }
  12. };
  13. console.log("I ran on first render only!");
  14. window.addEventListener('scroll', handleScroll);
  15. return () => {
  16. window.removeEventListener('scroll', handleScroll);
  17. };
  18. }, []);
  19. return (
  20. <>
  21. <div style={{backgroundColor: isVisible ? "red" : "yellow", height: "200vh"}}>{`Is The Second Element Visible : ${isVisible}`}</div>
  22. <div className={`aboutEncoteki ${isVisible ? 'fade-in' : ''}`} ref={aboutEncotekiRef} >
  23. {`Is Element Visible : ${isVisible}`}
  24. </div>
  25. </>
  26. );
  27. }
英文:

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/

  1. function App() {
  2. const [isVisible, setIsVisible] = React.useState(false);
  3. const aboutEncotekiRef= React.useRef();
  4. React.useEffect(() =&gt; {
  5. const handleScroll = () =&gt; {
  6. const element = aboutEncotekiRef.current;
  7. if (element) {
  8. const { top, bottom } = element.getBoundingClientRect();
  9. const isVisible = top &lt; window.innerHeight &amp;&amp; bottom &gt;= 0;
  10. setIsVisible(isVisible);
  11. }
  12. };
  13. console.log(&quot;I ran on first render only!&quot;);
  14. window.addEventListener(&#39;scroll&#39;, handleScroll);
  15. return () =&gt; {
  16. window.removeEventListener(&#39;scroll&#39;, handleScroll);
  17. };
  18. }, []);
  19. return (
  20. &lt;&gt;
  21. &lt;div style={{backgroundColor: isVisible ? &quot;red&quot;: &quot;yellow&quot;, height: &quot;200vh&quot;}}&gt;{`Is The Second Element Visible : ${isVisible}`}&lt;/div&gt;
  22. &lt;div className={`aboutEncoteki ${isVisible ? &#39;fade-in&#39; : &#39;&#39;}`} ref={aboutEncotekiRef} &gt;
  23. {`Is Element Visible : ${isVisible}`}
  24. &lt;/div&gt;
  25. &lt;/&gt;
  26. );
  27. }

huangapple
  • 本文由 发表于 2023年5月22日 20:10:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76306059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定