【问题标题】:How to use Redux in react-native to dispatch NetInfo connectivy change action?如何在 react-native 中使用 Redux 来调度 NetInfo 连接更改操作?
【发布时间】:2017-10-30 22:15:28
【问题描述】:

我希望能够在我的 react-native 应用中“持续”监控设备连接。

我已经成功地使用了 redux-thunk 和 redux。

其实我可以做到的

import { NetInfo } from 'react-native';

import {
    CONNECTION_CHECKING,
    CONNECTION_AVAILABLE,
    CONNECTION_UNAVAILABLE, 
} from './types';


export const connectionChecking = () => {
    return (dispatch) => {

        dispatch ({
            type: CONNECTION_CHECKING
        });

        NetInfo.getConnectionInfo()
            .then((connectionInfo) => {

                console.log('Connection info: ', connectionInfo);
                switch (connectionInfo.type) {
                    case 'cellular':
                        dispatch ({
                            type: CONNECTION_AVAILABLE,
                            payload: connectionInfo.type
                        });
                        break;
                    case 'wifi':
                        dispatch ({
                            type: CONNECTION_AVAILABLE,
                            payload: connectionInfo.type
                        });
                        break;
                    default:
                        dispatch ({
                            type: CONNECTION_UNAVAILABLE,
                        });
                }
            })
            .catch((error) => console.warn(error));

    };
};

但是,当连接发生变化时,我不知道如何调度新操作。

从 react-native 文档中我看到了这个:

NetInfo.addEventListener(
  'connectionChange',
  handleConnectivityChange
);

但是......如何在事件监听器中调度一个动作?

我试图将它添加到同一个动作文件中

NetInfo.addEventListener(
    'connectionChange', (connectionInfo)  => {
        return (dispatch) => {

            console.log('Connection info changed ', connectionInfo);
            switch (connectionInfo.type) {
                case 'cellular':
                case 'wifi':
                    dispatch ({
                        type: CONNECTION_AVAILABLE,
                        payload: connectionInfo.type
                    });
                    break;
                default:
                    dispatch ({
                        type: CONNECTION_UNAVAILABLE,
                    });
            }

        };
    }
);

我没有得到任何结果,没有 console.log,所以我认为这是错误的方式

【问题讨论】:

    标签: javascript react-native redux redux-thunk


    【解决方案1】:

    您只需要在可以访问dispatch 函数的地方设置您的事件侦听器。

    直接来自组件

    最简单的做法(允许完全取消订阅)是将它们设置在您最顶层的连接组件中:

    class MyApp extends Component {
      constructor(props) {
        super(props);
    
        // Dispatch an action from your event handler (and do whatever else)
        this._handleConnectionChange = (connectionInfo) => props.dispatch({ 
          type: 'CONNECTION_CHANGE', 
          connectionInfo
        });
    
        NetInfo.addEventListener('connectionChange', this._handleConnectionChange);
      }
    
      componentWillUnmount() {
        NetInfo.removeEventListener('connectionChange', this._handleConnectionChange);
      }
    }
    
    export default connect()(MyApp); // MyApp must be connected
    

    一点抽象 - 在 Thunk 中添加监听器

    我个人喜欢将这种东西包装在一个 thunk 中,以避免监听器处理混乱我的组件。这里的重点是 thunk 和连接的组件一样,可以访问 dispatch,因此通过在 thunk 的内部定义侦听器,我们可以调度操作(或更多 thunk)以响应更改。

    // connectionActions.js
    
    let handleConnectionChange;
    
    export function registerListeners() {
      return (dispatch) => {
        handleConnectionChange = (connectionInfo) => {
          dispatch(connectionChanged(connectionInfo));
        }
        NetInfo.addEventListener('connectionChange', handleConnectionChange);
      }
    }
    
    export function unregisterListeners() {
      return (dispatch) => {
        handleConnectionChange && NetInfo.removeEventListener('connectionChange', handleConnectionChange);
      }
    }
    
    function connectionChanged(connectionInfo) {
      return (dispatch) => {
        switch (connectionInfo.type) {
          case 'cellular':
            dispatch({
              type: CONNECTION_AVAILABLE,
              payload: connectionInfo.type
            });
            break;
          // ...Other cases
        }
      }
    }
    

    然后您可以从MyApp 分派registerListeners()unregisterListeners(),而不是在那里定义侦听器的详细信息:

    // app.js
    // ...other imports
    import * as connectionActions from './connectionActions'
    
    class MyApp extends Component {
      constructor(props) {
        super(props);
        // Dispatch your thunk to take care of the registration
        props.dispatch(connectionActions.registerListeners());
      }
    
      componentWillUnmount() {
        this.props.dispatch(connectionActions.unregisterListeners());
      }
    }
    
    export default connect()(MyApp)
    

    更抽象一点 - 用于监听的高阶组件

    在我有多个可能的顶级组件的应用程序中(例如,具有不同主页的不同构建变体,或不属于主导航器的登录屏幕),我喜欢采用这种样板并以更高的顺序包装它组件:

    // hoc/withNetListeners.js
    
    export default function withNetListeners(SourceComponent): {
      class HOC extends React.Component {
        constructor(props) {
          super(props);
          props.dispatch(connectionActions.registerListeners());
        }
    
        componentWillUnmount() {
          this.props.dispatch(connectionActions.unregisterListeners());
        }
    
        render() {
          return <SourceComponent {...this.props} />;
        }
      }
      return hoistStatics(HOC, SourceComponent); // Package hoist-non-react-statics
    }
    

    然后在任何组件中充当您的根:

    // app.js
    class MyApp extends Component {
      // ... Just your UI, no listeners ...
    }
    
    // Inject the listeners with a HOC. Make you `connect` last, because 
    // `withNetListeners` needs to be given access to `dispatch`.
    export default connect()(withNetListeners(MyApp))
    

    【讨论】:

    • 感谢您提供高质量的回答。我请您扩展“一点抽象”版本。在这种情况下,我无法理解在哪里以及如何调用 NetInfo.addEventListener。我的目标是在 'connectionActions.js' 文件中有一个动作,该动作将在主要组件挂载后调用(this.props.callNetInfoRegistration....()或类似的),这样我就可以在状态更改时处理连接更改,无论我在哪里需要
    • 没问题 - 我在该部分添加了一些说明。这有帮助吗? (另一个更新 - 刚刚意识到我忘了打电话给NetInfo.addEventListener!现在可能更清楚了..)
    • 再次更新以展示如何将它与connectionChanged thunk 事件处理程序一起使用。
    猜你喜欢
    • 2017-10-29
    • 2019-03-07
    • 2018-10-28
    • 2017-11-09
    • 2017-11-30
    • 1970-01-01
    • 2018-07-16
    • 2018-12-09
    • 2020-11-29
    相关资源
    最近更新 更多