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

3
我希望在所有组件中测试用户是否连接到互联网。
我可以在每个组件中使用"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)来实现吗?我猜使用高阶组件会减少一些复杂性,从而让你更加轻松。只是一个想法。 - Chaim Friedman
3个回答

3
我会为此创建一个高阶组件
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包复制非React特定的静态方法:

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 提供了该属性。我希望能够在我的应用程序中的所有组件中访问该属性。 - Jamgreen
你可以使用 withNetInfo() 装饰任何你想要的组件。它能给你更多的控制。 - Kerumen
但如果我给每个组件挂载添加事件监听器,会不会导致性能问题? - Jamgreen
这就是我不确定的地方。我们需要一些React大师来回答这个问题。 - Kerumen

1

1

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接