How to create a progress bar for an API request in React Native?

I am trying to make a simple pass counter that goes from 0% to 100% while my program selects weather data. The API request is made by getLocation() inside index.ios.js , which calls fetchWeather() inside weatherApi.js . Is there a way to measure the progress of my API request made by the fetch function? If not, what would be a good way to implement a loading bar?

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 Raining", subtitle: "You guessed it", highlight: ["Raining"], color:"#004A96", background:"#2F343A" }, Thunderstorm: { title: "Not Just Raining, It 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 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) 
+5
source share
1 answer

The fetch API does not include any callbacks , so your options are either using XMLHttpRequest , which is fully supported in React Native or a library that is essentially going to build on top of it. For example, you can change your fetchWeather function:

 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}); } } }); } 

Where progress is the callback in which you update the state. For example, in your component add a function:

 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 } } 

Then the call becomes:

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

An example adapted from MDN .

+4
source

Source: https://habr.com/ru/post/1260426/


All Articles