ReactJS 마우스 이동 스로틀

18173 단어 webdevreactjavascript
ReactJS에서 마우스 이동 이벤트를 제한합니다. 이벤트 핸들러를 조절하고 좌표를 state에 저장합니다. 후크는 구성 요소가 처음 마운트된 후에만 실행되어야 합니다.

쓰로틀링



스로틀링 예:
  • 나는 100보 이동하기로 결정했지만 모든 두 번째 단계를 건너뜁니다(Throttle every second step).
  • 20초 동안 움직이면서 손을 흔들기로 결정했지만 3초마다 손을 흔듭니다(3초 스로틀).

  • 나는 당신이 요점을 이해하기를 바랍니다.

    마우스 이동 이벤트




    console.clear();
    console.log({ React, ReactDOM });
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    function PrintMouseMoveEvent() {
      React.useEffect(() => {
        document.addEventListener('mousemove', (event) => {
          console.log('mousemove', event);
        });
      });
    
      return <h1>Open console to see mouse-move event output</h1>
    }
    
    ReactDOM
      .createRoot(document.getElementById('root'))
      .render(<PrintMouseMoveEvent />);
    


    마우스 이동 이벤트가 자주 발생합니다. 이벤트가 너무 많으면 성능 문제가 발생합니다. 아래의 Codepen 예제로 콘솔을 열어 사용해 보십시오.

    아래 그림에서 마우스 이동 이벤트를 볼 수 있습니다.

    ReactJS 철학



    상태를 사용하여 구성 요소를 제어합니다. ReactJS 철학에 따라 다음을 수행해야 합니다.

    마우스 이동 이벤트를 수신합니다.
    마우스 이동 이벤트를 상태에 저장합니다.
    저장된 좌표를 사용하여 헤더를 이동합니다.

    마우스 이동 이벤트는 마우스 좌표를 제공하며 가장 어려운 부분입니다.

    구성 요소 수명 주기



    다음은 기능 구성 요소에 적용됩니다!

    구성 요소에는 두 가지 유형의 수명 주기가 있다고 생각합니다.

    컴포넌트가 DOM에서 사용 가능해집니다.
    구성 요소 상태가 업데이트됩니다.

    컴포넌트 탄생



    구성 요소는 탑재될 때 초기 상태를 한 번만 사용합니다.

    나는 그것을 구성 요소의 탄생이라고 부르고 싶습니다.

    구성 요소에 상태를 설정해도 구성 요소가 파괴되지 않습니다.

    조건부 렌더링은 구성 요소 탄생의 예입니다.

    라이프 사이클 이해의 중요성



    후크는 종종 쓸모없는 구성 요소 업데이트의 소스입니다.

    가장 중요한 것은 내가 원할 때 훅이 실행되는 것입니다.

    마우스 이동 이벤트 리스너를 연결하는 것은 최초 생성 후에만 발생하면 됩니다.

    구성 요소를 제거하기 전에 마우스 이동 이벤트 리스너를 제거해야 합니다.

    ReactJS 마우스 이동 제한되지 않음



    이해하기 쉽습니다. 스로틀링은 복잡성 계층을 추가합니다.

    먼저 소스 코드:

    console.clear();
    console.log({ React, ReactDOM });
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    function createMousePosition(x, y) {
      return { x, y };
    }
    
    function MouseMove() {
      const [mousePosition, setMousePosition] = React.useState(createMousePosition(0, 0));
    
      // i absolutely don't want to rerun this hook at any other time
      // then initial mount and last unmount
      React.useEffect(() => {
        // saveMousePosition must be defined in the hook
        // when a hook calls a function that references state or props
        // they must be declared in dependency array
        // if saveMousePosition is outside of the hook
        // i would need to use React.useCallback to wrap it
        function saveMousePosition(event) {
          setMousePosition(createMousePosition(event.clientX, event.clientY));
        };
    
        document.addEventListener('mousemove', saveMousePosition);
        return () => {
          document.removeEventListener('mousemove', saveMousePosition);
        };
      }, [setMousePosition]);
    
      return (
        <h1
          style={{
            position: 'absolute',
            top: `${mousePosition.y}px`,
            left: `${mousePosition.x}px`,
            transform: 'translate(-50%, -50%)',
            margin: 0
          }}
        >
          reactjs mousemove non-throttled version
        </h1>
      );
    }
    
    const root = document.getElementById('root');
    ReactDOM.createRoot(root).render(<MouseMove />);
    


  • 구성 요소는 초기 좌표를 저장합니다.
  • 컴포넌트 생성 후 리스너를 연결합니다.
  • 컴포넌트가 죽기 전에 리스너를 제거하십시오.
  • 구성 요소의 상태를 업데이트합니다.

  • Codepen 실행 가능 예제:

    https://codepen.io/Flexos96/pen/eYVoYgJ?editors=0010

    ReactJS 마우스 이동 제한됨



    먼저 제한된 버전의 소스 코드:

    console.clear();
    console.log({ React, ReactDOM });
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    const DURATION = 10;
    
    const throttle = (function() {
      let timeout = undefined;
      return function throttle(callback) {
        if (timeout === undefined) {
          callback();
          timeout = setTimeout(() => {
            // allow another call to be throttled
            timeout = undefined;
          }, DURATION);
        }
      }
    })();
    
    /**
     * Wraps callback in a function and throttles it.
     * @returns Wrapper function
     */
    function throttlify(callback) {
      return function throttlified(event) {
        throttle(() => {
          callback(event);
        });
      }
    }
    
    function createMousePosition(x, y) {
      return { x, y };
    }
    
    function MouseMove() {
      const [mousePosition, setMousePosition] = React.useState(createMousePosition(0, 0));
    
      // i absolutely don't want to rerun this hook at any other time
      // then initial mount and last unmount
      React.useEffect(() => {
        const saveMousePosition = throttlify((event) => {
          setMousePosition(createMousePosition(event.clientX, event.clientY));
        });
    
        document.addEventListener('mousemove', saveMousePosition);
        return () => {
          document.removeEventListener('mousemove', saveMousePosition);
        };
      }, [setMousePosition]);
    
      return (
        <h1
          style={{
            position: 'absolute',
            top: `${mousePosition.y}px`,
            left: `${mousePosition.x}px`,
            transform: 'translate(-50%, -50%)',
            margin: 0,
            transition: `${DURATION}ms linear`,
          }}
        >
          reactjs mousemove throttled version
        </h1>
      );
    }
    
    const root = document.getElementById('root');
    ReactDOM.createRoot(root).render(<MouseMove />);
    


    유일한 차이점은 스로틀링입니다. 제한을 처리하는 두 가지 기능이 있습니다.
  • 스로틀 기능은 실행을 제한합니다.
  • throttlify는 인수를 감싸고 제한된 버전을 반환합니다.

  • 스로틀 기능으로 정리를 할 수 없습니다. 이벤트 핸들러에 대한 참조가 없습니다. Throttlify는 내가 정리할 수 있도록 제한된 버전을 반환합니다.

    Codepen 실행 가능 예제:

    https://codepen.io/Flexos96/pen/qBxvQPV?editors=0010

    좋은 웹페이지 즐겨찾기