简体   繁体   中英

Timeout for RefreshView in React Native Expo App

My current React Native Expo app has a ScrollView that implements RefreshControl . A user pulling down the ScrollView will cause the onRefresh function to be executed, which in turns call an action creator getSpotPrices that queries an API using axios .

Problem: If there is a network problem, the axios.get() function will take very long to time out. Thus, there is a need to implement the timing out of either axios.get() or onRefresh .

How can we implement a timeout function into RefreshControl ?

/src/containers/main.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ScrollView, RefreshControl } from 'react-native';

import MyList from '../components/MyList';
import { getSpotPrices } from '../actions';

class RefreshableList extends Component {

    onRefresh = () => {
        this.props.getSpotPrices();
    }

    render() {
        return (
            <ScrollView 
                refreshControl={
                    <RefreshControl 
                        refreshing={this.props.isLoading}
                        onRefresh={this._onRefresh}
                    />
                }>
                <MyList />
            </ScrollView>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        isLoading: state.currencies.isLoading,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        getSpotPrices: () => dispatch(getSpotPrices()),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(RefreshableList);

/src/actions/index.js

import api from "../utils/api";
import * as types from "../types";
import Axios from "axios";

const getSpotPrice = async () => {
  try {
    const res = await Axios.get(`https://api.coinbase.com/v2/prices/spot`);
    return parseFloat(res.data.data.amount);
  } catch (err) {
    throw new Error(err);
  }
};

export const getSpotPrices = () => async dispatch => {
  try {
    const price = await getSpotPrice();
    dispatch({
      type: types.CURRENCIES_SET,
      payload: price
    });
  } catch (err) {
    dispatch({
      type: types.CURRENCIES_FAILED_FETCH,
      payload: err.toString()
    });
  } finally {
    dispatch({
      type: types.CURRENCIES_IS_LOADING,
      payload: false
    })
  }
};

/src/reducers/currencies.js

import * as types from "../types";

const initialState = {
  data: {},
  isLoading: false,
};

export default (state = initialState, { type, payload }) => {
  switch (type) {

    case types.CURRENCIES_SET:
      return {
        ...state,
        data: payload,
        error: "",
        isLoading: false
      };

    case types.CURRENCIES_FAILED_FETCH:
      return {
        ...state,
        error: payload,
        isLoading: false
      };

    case types.CURRENCIES_IS_LOADING:
        return {
            isLoading: payload
        }

    default:
      return state;
  }
};
  1. Check if user is connected internet or not using the react-native-netinfo library

    NetInfo.fetch().then(state => { console.log("Connection type", state.type); console.log("Is connected?", state.isConnected); this.setState({ connected: state.isConnected }); });

    // Subscribe const unsubscribe = NetInfo.addEventListener(state => { console.log("Connection type", state.type); this.setState({ connected: state.isConnected }); }); // Unsubscribe unsubscribe(); <- do this in componentwillunmount

  2. Its generally a good practice to add a timeout, in all your api calls, in axios you can easily add a timeout option like:

await axios.get(url, { headers, timeout: 5000 })

so in your case modify the axios call as

await Axios.get( https://api.coinbase.com/v2/prices/spot , { timeout: 5000 } );

I have put timeout of 5 seconds you can modify the parameter according to your need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM