【问题标题】:Using NetInfo middleware in React Native with Redux在 React Native 中使用 NetInfo 中间件和 Redux
【发布时间】:2017-10-29 23:07:27
【问题描述】:

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

我可以在每个组件中使用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 变量填充所有组件,您通常会这样做吗?

【问题讨论】:

  • 不能用 HOC 实现同样的事情吗?我猜想使用 HOC 会降低一些复杂性,从而让您放心。只是一个想法。

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


【解决方案1】:

我会为此创建一个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;

【讨论】:

  • 这是一个很好的解决方案,但它只给了MyComponent这个道具。我希望能够访问我应用中所有组件中的道具。
  • 你可以用withNetInfo()装饰你想要的任何组件。它为您提供更多控制权。
  • 但是,如果我在每个单独的组件挂载中添加事件监听器,它不会带来性能问题吗?
  • 这就是我不确定的。我们需要一些 React 大师来回答这个问题。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多