You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用useRef()实现菜单按钮滚动淡出效果后自动复现问题求助

Hey there! Let's figure out why your menu button keeps reappearing after the fadeOut animation finishes. I’ve dealt with similar quirky animation issues in React before, so here are the most common reasons and fixes to try:

1. Your animation isn’t "sticking" after it ends

FadeOut animations (whether CSS transitions or keyframes) only affect the element during the animation duration. If you don’t explicitly set a persistent hidden state afterward, the browser will reset the element back to its original styles once the animation completes.

Fix:

  • Use a React state (like isHidden) to track the button’s final visibility status.
  • When the scroll trigger hits, start the animation, then listen for the animationend event to update the state once the fade is done.
  • Use that state to apply a permanent hidden class (with visibility: hidden or display: none) or lock the opacity to 0.

2. You’re directly modifying DOM styles with useRef, which gets reset on re-renders

React re-renders components when state/props change, and if you’re only updating ref.current.style.opacity directly, those changes can get overwritten if the component re-renders.

Fix:
Combine useRef with React state and CSS classes instead of raw DOM style edits. This keeps the visibility state tied to React’s rendering cycle, so it won’t get reset unexpectedly.

3. Your scroll event listener might be firing repeatedly or has conflicting logic

If you didn’t set up your scroll listener with a cleanup function (in useEffect), you could end up with multiple listeners triggering overlapping animations. Or your scroll logic might accidentally toggle the button back to visible when it shouldn’t.

Fix:

  • Wrap your scroll listener in a useEffect with proper cleanup to avoid duplicate listeners.
  • Add clear conditionals to only trigger the fadeOut when scrolling down past your threshold, and fadeIn only when scrolling back up below it.

Example Working Code

Here’s a revised approach that addresses all these issues:

import { useState, useEffect, useRef } from 'react';

function MenuButton() {
  const [isHidden, setIsHidden] = useState(false);
  const buttonRef = useRef(null);

  useEffect(() => {
    const handleScroll = () => {
      const scrollThreshold = 100; // Adjust this to your needs
      const hasScrolledPast = window.scrollY > scrollThreshold;

      if (hasScrolledPast && !isHidden) {
        // Start the fade animation
        buttonRef.current.classList.add('fade-out');
        
        // Wait for animation to end, then lock the hidden state
        const handleAnimationComplete = () => {
          setIsHidden(true);
          buttonRef.current.removeEventListener('animationend', handleAnimationComplete);
        };
        buttonRef.current.addEventListener('animationend', handleAnimationComplete);
      } else if (!hasScrolledPast && isHidden) {
        // Reset visibility when scrolling back up
        setIsHidden(false);
        buttonRef.current.classList.remove('fade-out');
      }
    };

    // Add scroll listener
    window.addEventListener('scroll', handleScroll);
    
    // Cleanup listener on unmount
    return () => window.removeEventListener('scroll', handleScroll);
  }, [isHidden]);

  return (
    <button
      ref={buttonRef}
      className={`menu-button ${isHidden ? 'permanently-hidden' : ''}`}
    >
      Menu
    </button>
  );
}

And the corresponding CSS:

.menu-button {
  opacity: 1;
  transition: opacity 0.3s ease; /* Smooth fade transition */
  /* Add your other button styles here */
}

.fade-out {
  opacity: 0;
}

.permanently-hidden {
  visibility: hidden;
  pointer-events: none; /* Prevent accidental clicks when hidden */
}

Bonus Tip for CSS Keyframe Animations

If you’re using CSS keyframes instead of transitions, make sure to set animation-fill-mode: forwards to keep the final animation state:

@keyframes fadeOut {
  from { opacity: 1; }
  to { opacity: 0; }
}

.fade-out {
  animation: fadeOut 0.3s forwards;
}

This should stop the button from popping back up after the fade animation finishes. Let me know if you need to tweak anything for your specific setup!

内容的提问来源于stack exchange,提问作者julBayonna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:39:08