在Redact中使用React Native中的NetInfo中间件

时间:2017-05-29 15:21:48

标签: javascript node.js reactjs react-native redux

我想在所有组件中测试用户是否已连接到互联网。

我可以在每个组件中使用NetInfo,但由于我使用redux,我认为使用中间件(?)可以更轻松地完成。

我用过

import { createStore, applyMiddleware } from 'redux';   

const netInfo = store => next => action => {
  const listener = (isConnected) => {
    store.dispatch({
      type: types.NET_INFO_CHANGED,
      isConnected,
    });
  };

  NetInfo.isConnected.addEventListener('change', listener);
  NetInfo.isConnected.fetch().then(listener);

  return next(action);  
};

const store = createStore(AppReducer, applyMiddleware(netInfo));

其中AppReducer只是combineReducers(navReducer, netInfoReducer, ...)

它确实有效,但我真的很担心这是否表现得足够好。它似乎只运行一次,但我永远不会删除听众或任何东西。

如果您想使用isConnected变量填充所有组件,通常会这样做吗?

3 个答案:

答案 0 :(得分:3)

我会为此创建一个Higher-Order Component

import React, { Component } from 'react';
import { NetInfo } from 'react-native';

function withNetInfo(WrappedComponent) {
  return class extends Component {
    constructor(props) {
      super(props);
      this.state = {};
      this.handleChange = this.handleChange.bind(this);
      NetInfo.isConnected.fetch().then(this.handleChange);
    }

    componentDidMount() {
      NetInfo.isConnected.addEventListener('change', this.handleChange);
    }

    componentWillUnmount() {
      NetInfo.isConnected. removeEventListener('change', this.handleChange);
    }

    handleChange(isConnected) {
      this.setState({ isConnected });
    }

    render() {
      return <WrappedComponent isConnected={this.state.isConnected} {...this.props} />;
    }
  }
}

export default withNetInfo;

然后你可以包装你想呈现的任何组件:

class MyComponent extends Component {
  render() {
    const { isConnected } = this.props;

    return(
      <View>
        <Text>
          {`Am I connected? ${isConnected}`}
        </Text>
      </View>
    );
  }
}

export default withNetInfo(MyComponent);

奖励:如果你想保留原始组件的静态方法(如果你已经定义了一些),你应该使用包hoist-non-react-statics来复制非反应特定静态:

import React, { Component } from 'react';
import { NetInfo } from 'react-native';
import hoistStatics from 'hoist-non-react-statics';

function withNetInfo(WrappedComponent) {
  class ExtendedComponent extends Component {
    constructor(props) {
      super(props);
      this.state = {};
      this.handleChange = this.handleChange.bind(this);
      NetInfo.isConnected.fetch().then(this.handleChange)
    }

    componentDidMount() {
      NetInfo.isConnected.addEventListener('change', this.handleChange);
    }

    componentWillUnmount() {
      NetInfo.isConnected. removeEventListener('change', this.handleChange);
    }

    handleChange(isConnected) {
      this.setState({ isConnected });
    }

    render() {
      return <WrappedComponent isConnected={this.state.isConnected} {...this.props} />;
    }
  }
  return hoistStatics(ExtendedComponent, WrappedComponent);
}

export default withNetInfo;

答案 1 :(得分:1)

使用中间件在redux存储中保留“isConnected”不应该存在性能问题,但是您需要确保仅添加一次侦听器。我使用https://github.com/michaelcontento/redux-middleware-oneshot来实现这一目标。

答案 2 :(得分:1)

我也考虑过中间件,但也害怕如何处理sub / unsub。我决定在我的AppContainer类的componentDidMountcomponentWillUnmount中添加和删除监听器,该类在我的MainNavigator中保存应用程序的其余部分。此类的生命周期应该遵循应用程序的生命周期,因此请确保正确地进行子/ unsub。但是,我也将使用redux操作来设置状态并在相关视图中监听它以显示“无连接”横幅。