Skip to content

Instantly share code, notes, and snippets.

@EduardoSP6
Last active January 14, 2025 21:42
Show Gist options
  • Save EduardoSP6/aacfcfc311cc7cb9027526f2227a1f62 to your computer and use it in GitHub Desktop.
Save EduardoSP6/aacfcfc311cc7cb9027526f2227a1f62 to your computer and use it in GitHub Desktop.
Prevent pull to refresh - React.js | Javascript

How to Prevent Page Refresh When Swiping Down on Mobile

In many mobile browsers, a "pull down" gesture at the top of the page can trigger the "pull-to-refresh" functionality. While useful in some scenarios, this behavior can be undesirable in web applications that utilize touch elements or where the page should not be reloaded.

We can use touch events (touchstart and touchmove) to detect when the user tries to "pull down" from the top of the page. In this case, we can prevent the default refresh action, ensuring that normal scrolling continues to work.

To do this, I created the component below:

import { ReactNode, useEffect } from "react";

export interface PreventPullToRefreshContainerProps {
  children: ReactNode;
}

const PreventPullToRefreshContainer = ({
  children,
}: PreventPullToRefreshContainerProps) => {
  useEffect(() => {
    let startY: number | null = null; // Para armazenar a posição inicial do toque.

    // verifica se o elemento possui scroll ativo.
    const isScrollable = (element: HTMLElement): boolean => {
      const style = window.getComputedStyle(element);
      const overflowY = style.overflowY;
      const canScroll = overflowY === "auto" || overflowY === "scroll";
      return canScroll && element.scrollHeight > element.clientHeight;
    };
    
    // verifica se o evento pode ser bloqueado no elemento alvo.
    const shouldPreventPullToRefresh = (target: HTMLElement): boolean => {
      let currentElement: HTMLElement | null = target;

      while (currentElement !== null && currentElement !== document.body) {
        if (isScrollable(currentElement)) {
          return false;
        }
        currentElement = currentElement.parentElement;
      }

      return true; 
    };
    
    const onTouchStart = (e: TouchEvent) => {
      // Salva a posição inicial do toque.
      startY = e.touches[0].clientY;
    };

    const onTouchMove = (e: TouchEvent) => {
      if (startY === null) return;

      const currentY = e.touches[0].clientY;
      const isPullingDown = currentY > startY;

      // Previne "pull-to-refresh" somente se no topo e arrastando para baixo.
      if (window.scrollY === 0 && isPullingDown) {
        const target = e.target as HTMLElement;
        if (shouldPreventPullToRefresh(target)) {
          e.preventDefault();
        }
      }
    };

    // Adiciona os event listeners
    document.addEventListener("touchstart", onTouchStart, { passive: true });
    document.addEventListener("touchmove", onTouchMove, { passive: false });

    // Remove os event listeners no cleanup
    return () => {
      document.removeEventListener("touchstart", onTouchStart);
      document.removeEventListener("touchmove", onTouchMove);
    };
  }, []);

  return <div className="touch-pan-x">{children}</div>;
};

export default PreventPullToRefreshContainer;

Check out the full article at: https://cafecomdev.blogspot.com/2025/01/como-evitar-atualizacao-da-pagina-ao.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment