외부 인터넷 연결을 기반으로 상태를 동적으로 변경-반응 (오프라인 / 온라인)


9

인터넷 연결의 가용성 플래그를 포함하는 React 구성 요소가 있습니다. UI 요소는 상태 실시간에 따라 동적으로 변경되어야합니다. 또한 플래그가 변경되면 기능이 다르게 작동합니다.

내 현재 구현은 간격을 사용하여 매초마다 Axios를 사용하여 원격 API를 폴링하고 그에 따라 상태를 업데이트합니다. 최소 계산 비용으로 1 초의 상태 오류를 제거하기 위해이 작업을 수행하는보다 세분화되고 효율적인 방법을 찾고 있습니다. 장치에 외부 인터넷 연결이있는 경우에만 온라인으로 간주

현재 구현 :

class Container extends Component {
  constructor(props) {
    super(props)
    this.state = {
      isOnline: false
    };
    this.webAPI = new WebAPI(); //Axios wrapper
  }

  componentDidMount() {
    setInterval(() => {
      this.webAPI.poll(success => this.setState({ isOnline: success });
    }, 1000);
  }

  render() {
    return <ChildComponent isOnline={this.state.isOnline} />;
  }
}

편집 :

외부 인터넷 연결을 감지 할 수있는 솔루션을 찾고 있습니다. 장치는 외부 연결이없는 LAN에 연결할 수 있습니다. 따라서 오프라인으로 간주됩니다. 장치가 외부 인터넷 리소스에 액세스 할 수있는 경우에만 온라인을 고려 합니다.


2
오프라인 상태인지 온라인 상태인지 알아야합니까? 또는 어떤 인터넷 연결?
tudor.gergely

네. 기본적으로 온라인 또는 오프라인입니다.
Nilanka Manoj

웹 소켓 연결을 노출하도록 API를 변경할 수 있습니까?
yadejo

답변:


2

방법 1 : 레거시 브라우저 API 사용- Navigator.onLine

브라우저의 온라인 상태를 반환합니다. 이 속성은 부울 값을 반환하며 true는 온라인을 의미하고 false는 오프라인을 의미합니다. 이 속성은 브라우저가 네트워크에 연결할 수있는 기능이 변경 될 때마다 업데이트를 보냅니다. 사용자가 링크를 따라갈 때 또는 스크립트가 원격 페이지를 요청할 때 업데이트가 발생합니다. 예를 들어 사용자가 인터넷 연결이 끊긴 후 링크를 ​​클릭하면 속성이 false를 반환해야합니다.

컴포넌트 라이프 사이클에 추가 할 수 있습니다.

Chrome 개발 도구를 사용하여 아래 코드로 재생합니다. 네트워크 탭에서 "온라인"을 "오프라인"으로 전환하십시오.

class App extends React.PureComponent {
  state = { online: window.navigator.onLine }
  
  componentDidMount() {
    window.addEventListener('offline', this.handleNetworkChange);
    window.addEventListener('online', this.handleNetworkChange);
  }
  
  componentWillUnmount() {
    window.removeEventListener('offline', this.handleNetworkChange);
    window.removeEventListener('online', this.handleNetworkChange);
  }
  
  handleNetworkChange = () => {
    this.setState({ online: window.navigator.onLine });
  }
  
  render() {
    return (
      <div>
       { this.state.online ? 'you\'re online' : 'you\'re offline' }
      </div>
    );
  }
}

ReactDOM.render(
  <App />
, document.querySelector('#app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>


그러나 이것이 원하는 것이 아니라고 생각합니다. 실시간 연결 검사기 를 원했습니다 .

방법 2 : 인터넷을 사용하여 인터넷 연결 확인

외부 인터넷 연결이 작동중인 경우 확인할 수있는 유일한 확인 방법입니다. 문제는 비용을 최소화하기 위해 어떤 서버를 호출해야 하는가입니다.

인터넷에는 많은 솔루션이 있으며, 빠른 204 상태로 응답하는 엔드 포인트는 다음과 같습니다.

  • Google 서버에 전화를 거는 경우 (가장 많이 테스트 된 (?))
  • 캐시 된 JQuery 스크립트 엔드 포인트 호출 (따라서 서버가 다운 된 경우에도 연결되어있는 한 스크립트를 계속 얻을 수 있어야 함)
  • 안정적인 서버에서 이미지를 가져 오십시오 (예 : https://ssl.gstatic.com/gb/images/v1_76783e20.png + 캐싱을 방지하기위한 날짜 타임 스탬프)

IMO, 서버 에서이 React 앱을 실행하는 경우 자신의 서버로 전화하는 것이 가장 적합합니다. 요청을 호출 /favicon.ico하여 연결을 확인 하라는 요청을 할 수 있습니다 .

(자신의 서버를 호출)이 아이디어는 많은 라이브러리에 의해 구현되어 Offline, is-reachable널리 사회에 걸쳐 사용된다. 직접 모든 것을 쓰지 않으려면 사용할 수 있습니다. (개인적으로는 NPM 패키지 is-reachable가 단순하다는 것을 좋아합니다 .)

예:

import React from 'react';
import isReachable from 'is-reachable';

const URL = 'google.com:443';
const EVERY_SECOND = 1000;

export default class App extends React.PureComponent {
  _isMounted = true;

  state = { online: false }

  componentDidMount() {
    setInterval(async () => {
      const online = await isReachable(URL);

      if (this._isMounted) {
        this.setState({ online });
      }
    }, EVERY_SECOND);
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  render() {
    return (
      <div>
       { this.state.online ? 'you\'re online' : 'you\'re offline' }
      </div>
    );
  }
}

테스트 서버 연결 편집

나는 당신이 현재 가지고있는 것이 이미 훌륭하다고 생각합니다. 올바른 엔드 포인트를 호출하고 있는지 확인하십시오.


비슷한 질문 :


8

https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event 를 사용할 수 있습니다

window.addEventListener('offline', (event) => {
    console.log("The network connection has been lost.");
});

그리고 https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event 다시 온라인 상태가되면 확인하기위한

window.addEventListener('online', (event) => {
    console.log("You are now connected to the network.");
});

내 상황에서 LAN을 외부에서 분리 할 수 ​​있습니다 :(
Nilanka Manoj

2

커스텀 훅 설정

온라인, 오프라인 이벤트로 후크를 설정하십시오. 그런 다음 상태를 업데이트하고 반환하십시오. 이렇게하면 가져 오기를 통해 앱의 어느 곳에서나 사용할 수 있습니다. 리턴 기능으로 정리하십시오. 그렇지 않으면 후크를 사용하는 구성 요소가 마운트 될 때마다 점점 더 많은 이벤트 리스너를 추가하게됩니다.

const onlineHook = () => {
  const {isOnline, setOnline} = React.useState();

  React.useEffect(() => {
    const goOnline = function(event){
      setOnline(true);
    });
    const goOffline = function(event){
      setOnline(false);
    });

    window.addEventListener('offline', goOffline);
    window.addEventListener('online', goOnline);

    return () => {
      window.removeEventListener('offline', goOffline);
      window.removeEventListener('online', goOnline);      
    }
  }, [])

  return isOnline
}

이것을 사용하려면 위의 후크를 가져 와서 이렇게 호출하십시오.

const isOnline = onlineHook(); // true if online, false if not

내 상황에서 LAN을 외부에서 분리 할 수 ​​있습니다 :(
Nilanka Manoj

3
firebase와 같은 소켓 서비스를 사용하는 경우 인터넷 연결을 캡처하는 내장 이벤트를 사용할 수 있습니다.
Joe Lloyd

제안 된 접근 방식에 대한 기본 코드 골격을 제공 할 수 있습니까?
Nilanka Manoj

2

모든 하위 구성 요소간에 공유 할 구성 요소를 작성할 수 있습니다.

익숙한:

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

export default function NetworkChecker() {

  const [networkStatus, setNetworkStatus] = useState(true)

  useEffect(() => {
    window.addEventListener('offline', (event) => {
      setNetworkStatus(false)
    });

    window.addEventListener('online', (event) => {
      setNetworkStatus(true)
    });

    return function cleanupListener() {
       window.removeEventListener('online',  setNetworkStatus(true))
       window.removeEventListener('offline', setNetworkStatus(false))
     }

  },[])

  if (networkStatus) {
    return <div className={"alert-success"}>Online</div>
  } else {
    return <div className={"alert-danger"}>Offline</div>
  }

}

이벤트 리스너를 제거하는 것을 잊었습니까?
gautamits
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.