如何监视反应组件中的网络状态变化

时间:2019-11-25 14:15:21

标签: javascript reactjs redux

有两个事件监听器在监视网络状态时显然很有用:

1. window.addEventListener('online', console.log('Online'));
2. window.addEventListener('offline', console.log('Offline'));

但是我不确定在哪里注册和使用它们。当我在componentDidMount中使用它们时,没有任何用处,因为只有安装了组件,监视才会发生。我想在一处监视网络状态,并在整个应用程序中使用它。为此,在redux中调度网络状态会更有帮助。但是问题是在哪里可以听到这些事件。

4 个答案:

答案 0 :(得分:1)

带有类组件的简化示例:

// In your main App component
componentDidMount() {
    window.addEventListener('online', () => this.props.setConnectivity('online'));
    window.addEventListener('offline', () => this.props.setConnectivity('offline'));

    // You don't need to worry about removeEventlistener if your main App component never unmounts.
}

// Action
const setConnectivity = (status) => ({
    type: 'SET_CONNECTIVITY',
    payload: status === 'online'
})

// Reducer
const connectivityReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'SET_CONNECTIVITY':
            return {
                ...state,
                isOnline: action.payload
            };
    }
};

// To let a component know about the connectivity status, simply use the flag from state:
const mapStateToProps = (state) => ({
    isOnline: state.connectivity.isOnline
});

// To react to status changes in any other component:
componentDidUpdate(prevProps) {
    const { isOnline } = this.props;

    if (!prevProps.isOnline && isOnline) {
        // We went online
    } else if (prevProp.isOnline && !isOnline) {
        // We went offline
    }
}

答案 1 :(得分:1)

这是React + Redux中在线/离线状态指示器的有效示例。

神奇之处在于拥有一个组件,该组件在组件的online事件中为componentDidMount事件添加了事件侦听器。然后,它通过Redux调度操作以更新商店中的在线状态。容器组件(在此示例中为MainContainer)可以将全局商店状态映射到道具,并且任何表示性组件都可以响应此属性更改而更新。

如果要使用Chrome在此页面上测试此在线指示器,请运行以下代码段:运行代码段,然后启动开发工具( F12 ),然后切换设备工具栏( Ctrl + Shift + M )(或“开发工具”窗口左上方的第二个图标),切换到响应式布局,然后根据需要在栏中切换在线/离线状态(如下图所示):

Chrome's device toolbar

function rootReducer(currentState, action) {
  currentState = currentState || { status: true }; // Initial State

  switch (action.type) {
    case 'SET_ONLINE_STATUS':
      return { ...currentState, status: action.status };
    default:
      return currentState; // Always return the state
  }
}

// Action Creators:
function setOnlineStatus(status) {
  return { type: 'SET_ONLINE_STATUS', status };
}

// Create Store
var rootStore = Redux.createStore(rootReducer);

// Map state and dispatch to props
function mapStateToProps(state) {
  return {
    status: state.status
  };
}

function mapDispatchToProps(dispatch) {
  return Redux.bindActionCreators({
    setOnlineStatus: setOnlineStatus
  }, dispatch);
}

// Connection indicator pure functional presentational component
var ConnectionIndicator = (props) => {
  return (<div>You are: {props.status ? 'online' : 'offline'}</div>);
};

var Main = React.createClass({
  render: function () {
    return (<div>
      <ConnectionIndicator status={this.props.status} />
    </div>);
  }
});

var OnlineWatcher = React.createClass({
  render() { return null; },
  componentDidMount() {
    window.addEventListener('online', () => {
      this.props.setOnlineStatus(true);
    })
    window.addEventListener('offline', () => {
      this.props.setOnlineStatus(false);
    })
  }
});


// Container components (Pass props into presentational component)
var MainContainer = ReactRedux.connect(mapStateToProps, mapDispatchToProps)(Main);
var OnlineWatcherContainer = ReactRedux.connect(mapStateToProps,
                                                mapDispatchToProps)(OnlineWatcher);

// Top-Level Component
var App = React.createClass({
  render: function () {
    return (
      <div>
        <MainContainer />
        <OnlineWatcherContainer />
      </div>
    );
  }
});

// Render to DOM
var Provider = ReactRedux.Provider; // Injects store into context of all descendents
ReactDOM.render(
  <Provider store={rootStore}>
    <App />
  </Provider>,
  document.getElementById('container')
);

	
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.13.0/polyfill.js"></script>
<div id="container">
  <!-- Yield to React -->
</div>

注意::在生产代码中,您还应该在online函数中取消订阅offlinecomponentWillUnmount事件。

我以this fiddle为起点。

答案 2 :(得分:1)

我建议使用此very new library

然后,您可以使用useNetworkStatus来获取所需的内容,例如:

import React from 'react';

import { useNetworkStatus } from 'react-adaptive-hooks/network';

const MyComponent = () => {
  const { effectiveConnectionType } = useNetworkStatus();

  let media;
  switch(effectiveConnectionType) {
    case 'slow-2g':
      media = <img src='...' alt='low resolution' />;
      break;
    case '2g':
      media = <img src='...' alt='medium resolution' />;
      break;
    case '3g':
      media = <img src='...' alt='high resolution' />;
      break;
    case '4g':
      media = <video muted controls>...</video>;
      break;
    default:
      media = <video muted controls>...</video>;
      break;
  }

  return <div>{media}</div>;
};

effectiveConnectionType-如果网络发生变化,则会发生变化,

navigator.connection.addEventListener('change', func)-这也会在onlineoffline

上触发

答案 3 :(得分:0)

首先,您应该具有带有操作和简化器的redux存储。您可以连接要存储的每个组件,并使用此事实来源。您可以在https://react-redux.js.org/introduction/quick-start

处找到文档和说明。

实际上,您可以找到使用在线状态Integrating Navigator.onLine into React-Redux

的示例