繁体   English   中英

如何在React Native中为API请求创建进度条?

[英]How can I create a progress bar for an API request in React Native?

当我的程序获取天气数据时,我正在尝试制作一个简单的进度计数器,从0%到100%。 API请求通过由getLocation()的内部index.ios.js它调用fetchWeather()的内部weatherApi.js 有没有办法测量fetch函数对我的API请求的进度? 如果没有,实施加载栏的好方法是什么?

weatherAPI.js

const rootUrl ='http://api.openweathermap.org/data/2.5/weather?appid=fcea54d0ceade8f08ab838e55bc3f3c0'

export const fetchWeather = (lat,lon) => {

    const url = rootUrl+'&lat='+lat+'&lon='+lon+"&units=metric"
    console.log(url)

  return fetch(url)
    .then(res => res.json())
    .then(json => ({
        temp: json.main.temp,
        weather: json.weather[0].main
    }))

}

index.ios.js

import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    StatusBar
    } from 'react-native'

import Icon from 'react-native-vector-icons/Ionicons'
import {fetchWeather} from './weatherAPI'
import Highlight from 'react-native-highlight-words'

const iconNames = {
    Default: 'md-time',
    Clear: 'md-sunny',
    Rain: 'md-rainy',
    Thunderstorm: 'md-thunderstorm',
    Clouds: 'md-cloudy',
    Snow: 'md-snow', 
    Drizzle: 'md-umbrella',
}

const phrases = {

    Default:{
        title: "Fetchin the Weather",
        subtitle: "Be patient, you're witnessing a miracle",
        highlight: ["Fetchin"],
        color: "#636363",
        background: "#9C9C9C"
    },

    Clear: {
        title: "CLEAR.",
        subtitle: "You Better Go Outside",
        highlight: ["CLEAR"],
        color:"#E32500",
        background: "#FFD017"
    },
    Rain: {
        title: "It's Raining",
        subtitle: "You guessed it",
        highlight: ["Raining"],
        color:"#004A96",
        background:"#2F343A"
    },
    Thunderstorm: {
        title: "Not Just Raining, It's Storming",
        subtitle: "Free shower",
        highlight: ["Storming"],
        color:"#FBFF46",
        background:"#020202"
    },
    Clouds: {
        title: "Clouds for Days",
        subtitle: "Cotton candy skies",
        highlight: ["Days"],
        color:"#0044FF",
        background: "#939393"

    },
    Snow: {
        title: "Oh Yeah Bud. It's Snowin'",
        subtitle: "Make a snow angel bud",
        highlight: ["Snowin'"],
        color:"#021D4C",
        background:"#15A678"

    },
    Drizzle: {
        title: "Just a Wee Ol' Drizzle Lads",
        subtitle: "Free shower",
        highlight: ["Wee", "Ol'"],
        color:"#dbdbdb",
        background:"#1FBB68"

    },
}

class App extends Component {


  componentWillMount() {

    this.state = {

        temp: 0,
        weather: 'Default'
    }   

  }

  componentDidMount() {
    this.getLocation()
}

  getLocation() {
    navigator.geolocation.getCurrentPosition(
      posData => fetchWeather(posData.coords.latitude,posData.coords.longitude)
      .then(res => this.setState({
        temp:Math.round(res.temp),
        weather: res.weather
      })),
      error => alert(error),
      {timeout: 10000}
      )
  }


    render(){
        console.log(this.state.weather)
        return(
        <View style={[styles.container, {backgroundColor: phrases[this.state.weather].background}]}>
          <StatusBar hidden={true}/>
            <View style={styles.header}>
            <Icon name={iconNames[this.state.weather]} size={80} color={'white'}/>
            <Text style={styles.temp}>{this.state.temp}°</Text>
            </View>
            <View style={styles.body}>
            <Highlight 
              style={styles.title}
              highlightStyle={{color: phrases[this.state.weather].color}}
              searchWords={phrases[this.state.weather].highlight}
              textToHighlight={phrases[this.state.weather].title}
              />
            <Text style={styles.subtitle}>{phrases[this.state.weather].subtitle}</Text>
            </View>
        </View>
        )
    }
}

const styles = StyleSheet.create({

    container: {
        flex:1,
        backgroundColor:'#FFD017'
    },


    header: {
        flexDirection:'row',
        alignItems:'center',
        justifyContent:'space-around',
        flex:1,

    },
    temp: {
        fontFamily: 'HelveticaNeue-Bold',
        fontSize: 45,
        color:'white'

    },

    body: {
        alignItems:'flex-start',
        justifyContent:'flex-end',
        flex:5,
        margin:10

    },

    title: {
        fontFamily: 'HelveticaNeue-Bold',
        fontSize: 90,
        color:'white',
        marginBottom:5

    },
    subtitle: {
        fontFamily: 'HelveticaNeue-Medium',
        fontSize: 16,
        color:'white'

    }



});

AppRegistry.registerComponent('IsItRaining', () => App)

fetch API不包含任何进度回调 ,因此您的选项要么使用在React Native中完全支持的XMLHttpRequest ,要么是基本上将在其上构建的库。 例如,您可以修改fetchWeather函数来执行以下操作:

export const fetchWeather = (lat,lon, progress) => {
return new Promise((resolve, reject) => {
    const url = rootUrl+'&lat='+lat+'&lon='+lon+"&units=metric"
    console.log(url)
    var oReq = new XMLHttpRequest();

    oReq.addEventListener("progress", progress);
    oReq.open('GET', url);
    oReq.send();
    oReq.onreadystatechange = function() {
        if (oReq.readyState == XMLHttpRequest.DONE) {
            let data = JSON.parse(oReq.responseText);
            resolve({temp: data.main.temp, weather: json.weather[0].main});
        }
    }
});
}

进度是一个回调状态,您可以在其中更新状态。 例如,在您的组件中,添加以下函数:

function updateProgress (oEvent) {
  if (oEvent.lengthComputable) {
    var progress = oEvent.loaded / oEvent.total;
    this.setState({progress})
  } else {
    // Unable to compute progress information since the total size is unknown
  }
}

然后,呼叫变为:

fetchWeather(posData.coords.latitude,posData.coords.longitude, this.updateProgress.bind(this)) fetchWeather(posData.coords.latitude,posData.coords.longitude)

该示例改编自MDN

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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