'Download file (fetched from API) via dynamic ID on onPress in react-native
I am trying to download file which is fetched from API via onPress.
Currently what i have done is fetched files from server using API. when i press on filename i got notification "download unsuccessfull" and i console "couldn't download file from the url i given n code".
I am doing right now is sending file name using onPress to "down_file" function to download file correspond to that name which is placed in server folder.
I tried to use the commented code but i got no files in '/data/user/0/com.aura/files/RNFetchBlobTmp_vzryqngv2ylp9wj0n3256m'
import * as React from 'react';
import { TextInput, View, StyleSheet, Image, Button, Alert, TouchableOpacity, Text, FlatList } from 'react-native';
import { StackNavigator } from 'react-navigation';
import RNFetchBlob from 'rn-fetch-blob';
import Toast from 'react-native-simple-toast';
import RNFS from 'react-native-fs';
export default class Students extends React.Component {
constructor(props) {
super(props);
this.state = {
pdf_list:[]
};
}
componentDidMount(){
const url = 'https://athirst-desertions.000webhostapp.com/download_pdf.php';
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
pdf_list: responseJson
})
})
.catch((error) => {
console.log(error);
})
}
down_file(user_pdf){
// RNFetchBlob
// .config({
// useDownloadManager : true,
// fileCache : true
// })
// .fetch('GET', 'http://athirst-desertions.000webhostapp.com/pdfs/{user_pdf}.pdf', {
// })
// .then((res) => {
// path: 'http://athirst-desertions.000webhostapp.com/pdfs/{user_pdf}.pdf';
// console.log('The file saved to ', res.path());
// })
const url = 'http://athirst-desertions.000webhostapp.com/pdfs/`${user_pdf}`.pdf';
const { config, fs } = RNFetchBlob;
const downloads = fs.dirs.DownloadDir;
return config({
// add this option that makes response data to be stored as a file,
// this is much more performant.
fileCache : true,
addAndroidDownloads : {
useDownloadManager : true,
notification : true,
path: downloads + '/' + user_pdf + '.pdf',
}
})
.fetch('GET', url);
}
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.pdf_list}
keyExtractor={(item, index) => index}
renderItem={({ item }) =>
<View style={styles.container}>
<Text onPress={this.down_file.bind(this, item.user_pdf)}>
{item.user_pdf}
</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
marginTop:100,
},
});
Solution 1:[1]
So the problem you are facing is that when you bind the function using
this.down_file.bind(this, item.user_pdf)
user_pdf inside the function becomes 'this' which is a reference.
Possible Solution
For me binding a function while passing it as a prop has never been a good option.
What I do is something like this, first instead of binding the function simply call it with the argument you want to pass
onPress={this.down_file(this, item.user_pdf)}
Now the problem here is that every time render is called the function is called and parts of your code will not work because everything is not ready at this time. To solve this change your function to return another function which will be called when you actually press it.
down_file(user_pdf) {
return () => {...}
}
With all your logic inside the curly braces with the ...
What this does is instead of executing your code inside the function every render now it simply returns a function that will execute your code when onPress is actually called. This behaves the same way as onPress={this.doOnPress}
PS: Remember to bind your function with 'this' in the constructor
i.e
this.down_file = this.down_file.bind(this)
because sometimes depending on the order of execution the wrong 'this' is used.
Hope this helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nemi Shah |