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

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

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(() =&gt; {
      const handleScroll = () =&gt; {
        const element = aboutEncotekiRef.current;
        console.log(&#39;element&#39;, element);
        if (element) {
          const { top, bottom } = element.getBoundingClientRect();
          const isVisible = top &lt; window.innerHeight &amp;&amp; bottom &gt;= 0;
          setIsVisible(isVisible);
          console.log(&#39;hello world&#39;);
        }
      };
  
      window.addEventListener(&#39;scroll&#39;, handleScroll);
      return () =&gt; {
        window.removeEventListener(&#39;scroll&#39;, handleScroll);
      };
    }, []);

My div

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

答案1

得分: 1

以下是您要翻译的内容:

更新的回答:

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

CODEPEN

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

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

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:

React.useEffect(() =&gt; {
  const handleScroll = (entries) =&gt; {
    const isVisible = entries[0].isIntersecting;
    setIsVisible(isVisible);
  };

  const options = {
    root: null, // Use the viewport as the root
    rootMargin: &quot;0px&quot;,
    threshold: 0.01, // Adjust the threshold as needed
  };

  const observer = new IntersectionObserver(handleScroll, options);
  const target = aboutEncotekiRef.current;

  if (target) {
    observer.observe(target);
  }

  return () =&gt; {
    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(() =&gt; {
  const handleScroll = () =&gt; {
    const element = aboutEncotekiRef.current;

    if (element) {
      const { top, bottom } = element.getBoundingClientRect();
      const isVisible = top &lt; window.innerHeight &amp;&amp; bottom &gt;= 0;

      setIsVisible(isVisible);
    }
  };
  
  console.log(&quot;I ran on first render only!&quot;);
  window.addEventListener(&#39;scroll&#39;, handleScroll);

  return () =&gt; {
    window.removeEventListener(&#39;scroll&#39;, handleScroll);
  };
}, []);
    
return (
&lt;&gt;
  &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;
  
  &lt;div className={`aboutEncoteki ${isVisible ? &#39;fade-in&#39; : &#39;&#39;}`} ref={aboutEncotekiRef} &gt;
    {`Is Element Visible : ${isVisible}`}
  &lt;/div&gt;
&lt;/&gt;
  );
}

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:

确定