Thay đổi trạng thái động dựa trên kết nối Internet bên ngoài - Phản ứng (ngoại tuyến / trực tuyến)


9

Tôi có một thành phần React, bao gồm cờ khả dụng của kết nối Internet. Các yếu tố UI phải được thay đổi linh hoạt theo thời gian thực. Ngoài ra, các chức năng hoạt động khác nhau với sự thay đổi của cờ.

Việc triển khai hiện tại của tôi thăm dò API từ xa bằng cách sử dụng Axios trong mỗi giây bằng cách sử dụng khoảng thời gian và trạng thái cập nhật tương ứng. Tôi đang tìm kiếm một cách chi tiết và hiệu quả hơn để thực hiện nhiệm vụ này để loại bỏ lỗi 1 giây của trạng thái với chi phí tính toán tối thiểu. Được coi là trực tuyến khi và chỉ khi thiết bị có kết nối Internet bên ngoài

Thực hiện hiện tại:

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} />;
  }
}

Đã chỉnh sửa:

Tìm kiếm một giải pháp có khả năng phát hiện kết nối Internet bên ngoài. Thiết bị có thể kết nối với mạng LAN không có kết nối bên ngoài. Vì vậy, nó được coi là ngoại tuyến. Người dùng trực tuyến khi và chỉ khi thiết bị có quyền truy cập vào các tài nguyên Internet bên ngoài.


2
Bạn có cần biết bạn ngoại tuyến hay trực tuyến? hoặc kết nối internet gì?
tudor.gergely

Vâng. Về cơ bản trực tuyến hoặc ngoại tuyến.
Nilanka Manoj

bạn có thể thay đổi API để nó hiển thị kết nối websocket không?
yadejo

Câu trả lời:


2

Phương pháp một: Sử dụng API trình duyệt cũ - Navigator.onLine

Trả về trạng thái trực tuyến của trình duyệt. Tài sản trả về một giá trị boolean, với ý nghĩa thực sự trực tuyến và ý nghĩa sai ngoại tuyến. Thuộc tính sẽ gửi các bản cập nhật bất cứ khi nào khả năng kết nối với mạng của trình duyệt thay đổi. Cập nhật xảy ra khi người dùng theo liên kết hoặc khi tập lệnh yêu cầu một trang từ xa. Ví dụ: tài sản sẽ trả về false khi người dùng nhấp vào liên kết ngay sau khi họ mất kết nối internet.

Bạn có thể thêm nó vào vòng đời thành phần của bạn:

Chơi với mã bên dưới bằng các công cụ phát triển Chrome - chuyển "Trực tuyến" sang "Ngoại tuyến" trong tab Mạng.

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>


Tuy nhiên, tôi nghĩ rằng đây không phải là những gì bạn muốn, bạn muốn một trình xác nhận kết nối thời gian thực.

Phương pháp hai: Kiểm tra kết nối internet bằng cách sử dụng nó

Xác nhận chắc chắn duy nhất bạn có thể nhận được nếu kết nối internet bên ngoài đang hoạt động là bằng cách sử dụng nó. Câu hỏi là máy chủ nào bạn nên gọi để giảm thiểu chi phí?

Có nhiều giải pháp trên internet cho việc này, bất kỳ điểm cuối nào phản hồi với trạng thái 204 nhanh là hoàn hảo, ví dụ:

  • gọi tới máy chủ Google (vì đây là máy chủ được thử nghiệm nhiều nhất (?))
  • gọi điểm cuối tập lệnh JQuery được lưu trong bộ nhớ cache của nó (vì vậy ngay cả khi máy chủ không hoạt động, bạn vẫn có thể nhận được tập lệnh miễn là bạn có kết nối)
  • hãy thử tìm nạp hình ảnh từ một máy chủ ổn định (ví dụ: https://ssl.gstatic.com/gb/images/v1_76783e20.png + dấu thời gian ngày để ngăn chặn bộ đệm)

IMO, nếu bạn đang chạy ứng dụng React này trên máy chủ, việc gọi đến máy chủ của bạn là hợp lý nhất, bạn có thể gọi yêu cầu tải của bạn /favicon.icođể kiểm tra kết nối.

Ý tưởng này (gọi máy chủ của riêng bạn) đã được thực hiện bởi nhiều thư viện, chẳng hạn như Offline, is-reachablevà được sử dụng rộng rãi trên cộng đồng. Bạn có thể sử dụng chúng nếu bạn không muốn tự viết mọi thứ. (Cá nhân tôi thích gói NPM is-reachablevì đơn giản.)

Thí dụ:

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>
    );
  }
}

Chỉnh sửa kết nối máy chủ thử nghiệm

Tôi tin rằng những gì bạn hiện đang ổn, chỉ cần đảm bảo rằng nó đang gọi đúng điểm cuối.


Câu hỏi SO tương tự:


8

Bạn có thể sử dụng 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 để kiểm tra khi bạn trực tuyến trở lại

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

LAN có thể bị ngắt kết nối bên ngoài trong tình huống của tôi :(
Nilanka Manoj

2

Thiết lập một hook tùy chỉnh

Thiết lập một hook với các sự kiện trực tuyến, ngoại tuyến. sau đó cập nhật trạng thái và trả lại Bằng cách này, bạn có thể sử dụng nó ở bất cứ đâu trong ứng dụng của mình bằng cách nhập. Hãy chắc chắn rằng bạn dọn dẹp với chức năng trả lại. Nếu bạn không, bạn sẽ thêm nhiều người nghe sự kiện hơn mỗi lần một thành phần sử dụng giá treo.

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
}

Để sử dụng, chỉ cần nhập hook ở trên và gọi nó như thế này.

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

LAN có thể bị ngắt kết nối bên ngoài trong tình huống của tôi :(
Nilanka Manoj

3
Nếu bạn sử dụng một dịch vụ được cắm như firebase, bạn có thể sử dụng một sự kiện tích hợp để nắm bắt kết nối internet.
Joe Lloyd

bạn có thể cung cấp một bộ mã cơ bản cho cách tiếp cận được đề xuất.
Nilanka Manoj

2

Bạn có thể tạo một thành phần để chia sẻ giữa tất cả các thành phần con

đã sử dụng:

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>
  }

}

Bạn quên loại bỏ người nghe sự kiện?
gautamits
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.