source

브라우저 탭의 포커스가 React에 있는지 확인합니다.JS

itover 2023. 2. 11. 09:13
반응형

브라우저 탭의 포커스가 React에 있는지 확인합니다.JS

리액트JS에 웹사이트가 있어요탭이 포커스가 맞거나 숨겨질 때마다 콜백을 받고 싶다.Page Visibility API를 발견했는데 ReactJS에서 사용하는 방법을 알 수 없습니다.

콜백을 등록하는 라이프 사이클 방법은 무엇입니까?

React 16.8에서 후크를 사용하여 구축했습니다.

import React, { useEffect } from "react";

// User has switched back to the tab
const onFocus = () => {
    console.log("Tab is in focus");
};

// User has switched away from the tab (AKA tab is hidden)
const onBlur = () => {
    console.log("Tab is blurred");
};

const WindowFocusHandler = () => {
    useEffect(() => {
        window.addEventListener("focus", onFocus);
        window.addEventListener("blur", onBlur);
        // Calls onFocus when the window first loads
        onFocus();
        // Specify how to clean up after this effect:
        return () => {
            window.removeEventListener("focus", onFocus);
            window.removeEventListener("blur", onBlur);
        };
  }, []);

    return <></>;
};

export default WindowFocusHandler;

이 조작은 유효합니다.

componentDidMount() {
    window.addEventListener("focus", this.onFocus)
}

componentWillUnmount() {
    window.removeEventListener("focus", this.onFocus)
}

onFocus = () => {
    //
}

편집: "blur"도 마찬가지이며 탭이 숨겨질 때 작동합니다.

@Assaf의 회답에서 훅을 사용한 사용을 확인합니다.

확인할 수 있는 신뢰할 수 있는 방법이 없기 때문에 몇 가지 방법을 조합할 필요가 있습니다.리액트 훅의 콘텍스트를 다음에 나타냅니다.

import React, { useState, useEffect } from 'react'

export const WindowContext = React.createContext(null)

export const WindowContextProvider = props => {
  const [windowIsActive, setWindowIsActive] = useState(true)


  function handleActivity(forcedFlag) {
    if (typeof forcedFlag === 'boolean') {
      return forcedFlag ? setWindowIsActive(true) : setWindowIsActive(false)
    }

    return document.hidden ? setWindowIsActive(false) : setWindowIsActive(true)
  }

  useEffect(() => {
    const handleActivityFalse = () => handleActivity(false)
    const handleActivityTrue = () => handleActivity(true)

    document.addEventListener('visibilitychange', handleActivity)
    document.addEventListener('blur', handleActivityFalse)
    window.addEventListener('blur', handleActivityFalse)
    window.addEventListener('focus', handleActivityTrue )
    document.addEventListener('focus', handleActivityTrue)

    return () => {
      window.removeEventListener('blur', handleActivity)
      document.removeEventListener('blur', handleActivityFalse)
      window.removeEventListener('focus', handleActivityFalse)
      document.removeEventListener('focus', handleActivityTrue )
      document.removeEventListener('visibilitychange', handleActivityTrue )
    }
  }, [])

  return <WindowContext.Provider value={{ windowIsActive }}>{props.children}</WindowContext.Provider>
}

는 이 도서관을 찾았다.도움이 될 수도 있어요.

당신의 문제를 해결하는 방법은 다음과 같습니다.

import React from 'react';
import PageVisibility from 'react-page-visibility';

class YourComponent extends React.Component {
    state = {
      isWindowInFocus: true,
    }
    componentDidMount() {
      const { isWindowInFocus } = this.props;
      if (!isWindowInFocus) {
        // do something
      }
    }

    listentoWindow = isVisible => {
      this.setState({
        isWindowInFocus: isVisible,
      });
    }
    render() {
      return (
        <PageVisibility onChange={this.listentoWindow}>
          <div>
           Your component JSX
          </div>
        </PageVisibility>
      );
    }
}

사용자가 탭 사이를 전환하는지, 태스크바에서 아이콘을 더블 클릭하여 브라우저를 최소화할 수 있는지 여부를 감지하는 방법 등 필요한 기능을 모두 제대로 하지 못했습니다.

여러 번 작업을 중단했지만 올바른 상태를 관리하거나 태스크바 아이콘에서 최소화할 때 작동하지 않거나 여러 작업을 계속 수행할 수 없었습니다.

포커스가 바뀔 때마다 서버를 요청해야 했기 때문에 위의 상황은 조금 '아니오'였습니다.

그래서 제가 한 일은 이렇습니다.

const DetectChatFocus = () => {
    const [chatFocus, setChatFocus] = useState(true);

    useEffect(() => {
        const handleActivityFalse = () => {
            setChatFocus(false);
            serverRequest(false);
        };

        const handleActivityTrue = () => {
            setChatFocus(true);
            serverRequest(true);
        };

        window.addEventListener('focus', handleActivityTrue);
        window.addEventListener('blur', handleActivityFalse);

        return () => {
            window.removeEventListener('focus', handleActivityTrue);
            window.removeEventListener('blur', handleActivityFalse);
        };
    }, [chatFocus]);
};

export default DetectChatFocus;

현재 이 기능은 Chrome과 Firefox 모두에서 매우 잘 동작하고 있습니다.주요 컴포넌트 또는 필요한 장소에서 초기화하기만 하면 됩니다.이 모든 시나리오에서 윈도 포커스를 추적하여 동작당1개의 서버만 요구합니다.

최신 후크:

import { useCallback, useEffect, useState } from "react";

const useTabActive = () => {
  const [visibilityState, setVisibilityState] = useState(true);

  const handleVisibilityChange = useCallback(() => {
    setVisibilityState(document.visibilityState === 'visible');
  }, []);

  useEffect(() => {
    document.addEventListener("visibilitychange", handleVisibilityChange)
    return () => {
      document.removeEventListener("visibilitychange", handleVisibilityChange)
    }
  }, []);

  return visibilityState;
}

export default useTabActive;

Document.visibilityState 사용

보다 완전하고 최적화된 후크:

import React, { useState, useEffect } from 'react'
import _ from 'lodash'

export default function useIsWindowFocused(): boolean {
    const [windowIsActive, setWindowIsActive] = useState(true)

    const handleActivity = React.useCallback(
        _.debounce(
            (e: { type: string }) => {
                if (e?.type == 'focus') {
                    return setWindowIsActive(true)
                }
                if (e?.type == 'blur') {
                    return setWindowIsActive(false)
                }
                if (e?.type == 'visibilitychange') {
                    if (document.hidden) {
                        return setWindowIsActive(false)
                    } else {
                        return setWindowIsActive(true)
                    }
                }
            },
            100,
            { leading: false },
        ),
        [],
    )

    useEffect(() => {
        document.addEventListener('visibilitychange', handleActivity)
        document.addEventListener('blur', handleActivity)
        window.addEventListener('blur', handleActivity)
        window.addEventListener('focus', handleActivity)
        document.addEventListener('focus', handleActivity)

        return () => {
            window.removeEventListener('blur', handleActivity)
            document.removeEventListener('blur', handleActivity)
            window.removeEventListener('focus', handleActivity)
            document.removeEventListener('focus', handleActivity)
            document.removeEventListener('visibilitychange', handleActivity)
        }
    }, [])

    return windowIsActive
}

직접 상태를 보는 것이 더 간단하다고 생각합니다.document.visibilityState, 다시 돌아오기 때문에'visible'또는'hidden':

const [visibilityState, setVisibilityState] = useState('visible')

useEffect(() => {
  setVisibilityState(document.visibilityState)
}, [document.visibilityState])

언급URL : https://stackoverflow.com/questions/49902883/check-if-the-browser-tab-is-in-focus-in-reactjs

반응형