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

Posted

技术标签:

【中文标题】如何在 React Native 中为 API 请求创建进度条?【英文标题】:How can I create a progress bar for an API request in React Native? 【发布时间】:2017-04-11 17:58:10 【问题描述】:

我正在尝试制作一个简单的进度计数器,在我的程序获取天气数据时从 0% 变为 100%。 API 请求由index.ios.js 内部的getLocation() 发出,它调用weatherApi.js 内部的fetchWeather()。有没有办法衡量我的 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)

【问题讨论】:

浏览器中有 onProgress 事件。不确定如何在 react-native 中使用 node.js。也许你应该尝试另一个 XHR 库。 查看axios 和这个library @LaurentL,我看到你总是说天气好! ;) 太棒了,谢谢大家的帮助!我会看看这些建议。 @free-soul haha​​h 很高兴你明白了 ;) 【参考方案1】:

fetch API 不包括any progress callbacks,因此您的选择是使用XMLHttpRequest,它在 React Native 中得到完全支持,或者一个基本上将在此基础上构建的库。例如,你可以修改你的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);
        
    
);

progress 是更新状态的回调。例如,在您的组件中,添加函数:

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。

【讨论】:

哇!这是一个比我想象的更好的答案!非常感谢您花时间研究我的问题并实际编写代码来演示它。 很高兴!如果您在实施它时遇到任何问题,请告诉我们:)

以上是关于如何在 React Native 中为 API 请求创建进度条?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ObjectC 中为 React Native 桥接 Swift View

如何在 react-native 中为特定组件传递样式道具

如何在 React Native 中为 useRef 钩子设置 Typescript 类型?

如何在 React Native 中为 TextInput 设置 lineHeight 样式?

如何在 Visual Studio Code 中为 React Native 设置调试?

当您不知道内容的大小时,如何在 react native 中为高度设置动画?