React Native Image with 'Bearer' authentication token - react-native

In React Native I can use images with <Image source={{uri: 'http://my.server.com/user/id/image/id.png'}} />
The problem is that user images are protected by JWT token which I pass in the header.
Is it possible to somehow include that additional header?
What are my other options?
Thanks!

You can send headers in the source prop.
<Image
source={
{ uri: 'https://yourdomain.com/get-image',
headers: {
Authorization: 'Bearer xyz'
}
}
}/>
you can specify other parameters as well:
ImageSourcePropType.js

For me the answer from blink281 didn't work. It seems this is a common Android problem according to this thread https://github.com/facebook/react-native/issues/25945 and while writing this it's not fixxed. I was looking for another solution and the answer from Samuli Hakoniemi helped me build one, so i wanted to share a fully working example as his Link is not working anymore.
I created an external Component called NetworkImage for this.
import React from "react";
import { StyleSheet, View, Image } from "react-native";
class NetworkImage extends React.Component {
constructor(props) {
super(props);
this.state = {
base64: null,
};
this.style = props.style;
this.imageId = props.imageId;
this.token = props.token;
}
componentDidMount() {
var imageUri = "/auth/diary/image/" + this.imageId;
fetch(imageUri, {
method: "GET",
headers: {
Pragma: "no-cache",
"x-access-token": this.token,
},
redirect: "follow",
})
.then((res) => res.text())
.then((content) => {
let data =
"data:image/jpeg;base64," +
content.substring(1, content.length - 1);
this.setState({
base64: data,
});
});
});
}
render() {
return <Image style={this.style} source={{ uri: this.state.base64 }} />;
}
}
export default NetworkImage;
In this case i had to prepend "data:image/jpeg;base64," because the data i got is raw without the datatype.

import RNFetchBlob from "rn-fetch-blob";
const { config, fs } = RNFetchBlob;
let PictureDir = fs.dirs.PictureDir;
let date = new Date();
let options = {
fileCache: true,
addAndroidDownloads: {
//Related to the Android only
useDownloadManager: true,
notification: true,
path:
PictureDir +
"/Report_Download" +
Math.floor(date.getTime() + date.getSeconds() / 2),
description: "Risk Report Download",
},
};
config(options)
.fetch('GET', url, {
Authorization: token,
})
// when response status code is 200
.then((res) => {
// the conversion is done in native code
console.log(JSON.stringify(res));
alert('report download successfully')
})
// Status code is not 200
.catch((errorMessage, statusCode) => {
// error handling
console.log('errorMessage', errorMessage);
console.log('statusCode', statusCode);
})
that's all. enjoy your coding...

Your options are this one: https://rnplay.org/apps/UowZmw (in order to see the simulator, type document.querySelector('.editor-container').style.width = '50%' in dev console, RNPlay is a bit broken with lengthy content).
Basically what you do is to:
1. serve your images as blobs
2. fetch them with fetch() to the app.
3. use base64 data as content of uri property
Do this in your componentWillMount():
fetch(YOUR_IMAGE_URI, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + 'TOKEN'
}
}
).then((res) => res.text())
.then((content) => {
this.setState({
base64: content
})
})
You may notice I use res.text() instead of res.blob(). This is because, while writing this, RN doesn't support .blob().
And this goes to render():
return (
<Image style={styles.base64} source={{uri: this.state.base64}} />
)

Related

How Can I Use a Component by Functions Response in React Native?

I'm trying to show a Lottie animation if the API response true. Here is my code:
export default class Register extends Component{
constructor(props){
super(props);
this.state = {
//variables
};
}
buttonClick = () =>{
//variables
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({variables})
};
fetch('api_url',requestOptions)
.then((response) => { return response.json() } )
.catch((error) => console.warn("fetch error:", error))
.then((response) => {
console.log(response)
if(response == "true"){
<LottieView
style={styles.success}
source = {require("./lottie/success.json")}
autoPlay = {true}
loop={false}
/>
}
})
}
render(){
return (
//textinputs and buttons
)
}
}
but the animation not showing up. I know it because of LottieView not in "render and return" parts but I don't know how can I fix it.
Add a useState isFetched, default value is false. If response is true, change state to true.
In render add this:
isFetched && (
<LottieView
style={styles.success}
source = {require("./lottie/success.json")}
autoPlay = {true}
loop={false}
/>
)

How to store API response in state And pass this response value to another screen as params in react native

I am new to react native. I have created A screen. Where I am getting response from API. but now I want to store that response in state. and I want to send that value to another screen by navigation params.
my response is like this ->
Array [
Object {
"phpid": 10,
},
]
here is my code
constructor(props) {
super(props);
this.state={
};
}
fetch('https://xuz.tech/Android_API_CI/uploaddata/t_details?query=', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
body: JSON.stringify([{"==some values=="}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
return response.json();
render(){
return (
<View style={{flex: 1}}>
color="black" onPress={() => this.props.navigation.navigate("FormItems",{i want to send value to formitems})} />
</View>
)}
Set your state once you receive your response, then use your state as params when navigating. Once your fetch has been resolved:
this.setState({ response: response.json() });
Sending params to another screen is fairly simple, you just need to pass an object as the second parameter to navigate.
this.props.navigation.navigate('FormItems', {
form: this.state.response,
});
The receiving component will then need to read those params:
class DetailsScreen extends React.Component {
render() {
const { navigation } = this.props;
return (
<Text>{JSON.stringify(navigation.getParam('form', 'some default'))}</Text>
}
}
A full explanation on how to use params with react-navigation v4 can be found here: https://reactnavigation.org/docs/4.x/params
Use it like this. first initialise the state and when you get data from api set the data in state and when button press pass the data to new screen in params.
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class Example extends Component {
state = {
data: [], // initialize empty state
};
componentWillMount() {
this.requestData();
}
requestData = () =>{
fetch('https://xuz.tech/Android_API_CI/uploaddata/t_details?query=', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
body: JSON.stringify([{"==some values=="}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
this.setState({
data:response //set data in state here
})
})
}
render() {
return (
<View style={{ flex: 1 }}>
<Button
color="black"
onPress={() =>
this.props.navigation.navigate('FormItems', {
data: this.state.data, // pass data to second screen
})
}
/>
</View>
);
}
}

Image is not displaying even though it has correct source uri in React-Native

I want to display profile image on profile page. When I sign in, I receive profile image information from PHP server.
So when I login, I saved it to AsyncStorage and after navigate to the profile page, I got that information from AsyncStorage. And set it to Image tag source. But image profile image is not displaying.
The weird thing is that, in that profile page, if I save the code in vscode editor (In debug state), then it shows image. How to display image in profile image?
What I did.
I tried to send image url as parameter to the profile page. In the profile page, I confirmed that image url was received successfully in console. But it also didn't display image. That is my code.
Login.js
loginHandle = async () => {
let details = {
'email': email,
'password': password
};
let formBody = [];
for (let property in details) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch(config.auth.login, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Auth-Key': 'simplerestapi'
},
body: formBody
})
.then((response) => response.json())
.then(async (responseJson) => {
console.log('status =>', responseJson['status']);
if (responseJson['status'] == 200) {
console.log('--', responseJson);
await AsyncStorage.setItem('photoURL', JSON.stringify(responseJson['photo_url']))
console.log('profile_image', (await AsyncStorage.getItem('photoURL')).toString())
this.props.navigation.navigate('Gallery', { 'profile': JSON.stringify(responseJson['photo_url']) })
}
})
.catch((err) => {
console.log(JSON.stringify(err));
})
}
Gallery.js
componentDidMount = async () => {
// const avatar = this.props.navigation.getParam('profile') // not working.
// console.log('avatar=>', avatar) (Edited) // Exactly received parameter from Login.js
const avatar = (await AsyncStorage.getItem('photoURL')).toString()
this.setState({ avatar: avatar })
}
render() {
return (
<Image source={this.state.avatar} style={{ width: 100, height: 100 }} />
)
}
Image takes an ImageSourcePropType for its source prop. Which is defined as {uri?: string}.
Thus it should be :
<Image source={{uri: this.state.avatar}} style={{width: 100, height: 100}}/>
More about the source prop here : https://reactnative.dev/docs/image.html#source

Displaying multiple data in react native

I am pretty new to react native. I am currently grabbing data from my node.js and trying to show all the data I grabbed into my View. In react.js, i did
documnet.getElementById.append().
What is the best way to do it in react native?
my code looks something like this
class GlobalRankings extends Component{
constructor(){
super();
this.state = {
}
this.getGlobalRankings();
}
getGlobalRankings(){
var request = new Request(checkEnvPort(process.env.NODE_ENV) + '/api/global_rankings', {
method: 'GET',
headers: new Headers({ 'Content-Type' : 'application/json', 'Accept': 'application/json' })
});
fetch(request).then((response) => {
response.json().then((data) => {
console.log(data);
for (var i in data.value){
console.log(data.value[i]); //where i grab my data
}
});
}).catch(function(err){
console.log(err);
})
}
render(){
return(
<View style={styles.container}>
// want my data to be here
</View>
)
}
}
Thanks for all the help
You can make an array in state in constructor, this.state = { arr: [] }
Then you assign the data array you get from the response.
fetch(request).then((response) => {
response.json().then((data) => {
this.setState({ arr: data.array });
});
}).catch(function(err){
console.log(err);
});
Then in the component body,
<View style={styles.container}>
{
this.state.arr.map((value, index) => {
return(
<Text key={index}>{value.text}</Text>
);
})
}
</View>

Fetching Image from Server with a React Native App

I'm building a mobile app with a Springboot Rest API backend and a React-Native Frontend.
I'm able to upload a picture from the react-native API to Springboot API and to store it in my postgres database as byte[].
I'm able to retrieve this picture with a simple Get Request tested by Postman.
BUT I'm not able to fetch this image and to display it in my React Native app.
I understood there is a problem to use blob file immediately with react native but I didnt see how to handle it.
Here is my fetch function :
export const getAquariumPicture = async (
aquariumId: string
): Promise<ImageSourcePropType | any> => {
const suffixUrl = "api/downloadAquariumPicture/";
const urlService = urlServer + suffixUrl + aquariumId;
try {
const token = await getData("token");
const response = await fetch(urlService, {
method: "GET",
headers: {
Authorization: token
}
});
return response;
} catch (error) {
console.error(error);
}
};
how can I use this response to pass it as source in an Image balise ?
Here how I'm trying to use the photo :
if (rootStore.tankStore.tankImageState === "pending") {
rootStore.tankStore.storeGetImageTank();
}
const photo = rootStore.tankStore.tankPicture;
console.log("photo = " + photo);
return (
<TouchableOpacity onPress={() => choosePicture()}>
<Image source={cameraIcon} style={styles.icon} />
{photo != null ? (
<Image source={photo} style={styles.photo} />
) : (
<ActivityIndicator />
)}
</TouchableOpacity>
);
In fact I found a solution :
<Image
source={getAquariumImageSource(RootStore.tankStore.tankList[0].id)}
style={styles.photo}
/>
export const getAquariumImageSource = (id: string): ImageSourcePropType => {
return {
uri: `${urlServer}api/downloadAquariumPicture/${id}`,
method: "GET",
headers: {
Pragma: "no-cache",
Authorization: RootStore.memberStore.token
},
cache: "reload"
};
};