Reputation: 21
I am trying to render an image being called within an asynchronous function, but the value is not assigned based on API data response.
Code:
import React from 'react';
import { TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Icon2 from 'react-native-vector-icons/MaterialCommunityIcons';
import axios from 'axios';
import { Container, Left, Avatar, Info, Name, Time } from './styles';
export default function Appointments({ data }) {
asd = async () => {
const user = data.item.userLogin.toLowerCase();
const response = await axios.get(
`https://api4.successfactors.com/odata/v2/Photo?$filter=tolower(userId) eq '${user}'`,
{
auth: {
username: 'Apiuser',
password: 'Apipass',
},
}
);
const encodedData = response.data.d.results[0].photo.toString();
console.log(encodedData);
return encodedData;
};
return (
<Container>
<Left>
<Avatar
source={{
uri: `data:image/png;base64,${this.asd()}`,
}}
/>
{console.log(this.asd())}
<Info>
<Name>
{data.item.userOnDesk} {'\n'}({data.item.userLogin})
</Name>
<Time>
<Icon2 name="office-building" size={20} color="#000" />
Prédio: {data.item.Predio}
</Time>
<Time>
<Icon2 name="chair-school" size={20} color="#000" />
Mesa: {data.item.Desk}
</Time>
<Time>{data.item.Andar} ºAndar</Time>
</Info>
</Left>
<TouchableOpacity onPress={() => {}}>
<Icon name="person" size={20} color="#005BAF" />
</TouchableOpacity>
</Container>
);
}
How do I load the variable before executing a return? I need my method of rendering the image to be asynchronous, if I put the "Appointments" function asynchronous, it doesn't work.
Upvotes: 0
Views: 5662
Reputation: 455
Why it does not work
asd() is an async function. That means, it will return a promise, NOT the value (your base64 string). Read more about that here.
How it can be solved
Well, you could just do ${await this.asd()}
. Because you are using await, you'd have to make render() async. But that is not possible in react. Besides, you'd be refetching the data on every component rerender.
A better approach would be to put the data in the state of your component:
// You can supply a default value as argument to useState()
const [avatarSrc, setAvatarSrc] = React.useState("");
// To retrieve the value:
<Avatar
source={{
uri: avatarSrc,
}}
/>
Then you can fetch your data with the useEffect hook:
React.useEffect(() => {
asd()
.then((data) => setAvatarSrc(`data:image/png;base64,${data}`))
}, []);
Note the empty array as second parameter. This prevents from refetching on every new render, see https://css-tricks.com/run-useeffect-only-once/.
Upvotes: 1
Reputation: 31683
If you call this.asd()
you will just render [object Promise]
because asd
is an async function, which returns a promise.
You need to load the photo in useEffect(() => { /* loado the photo */}, [])
export default function Appointments({ data }) {
const [uri, setUri] = React.useState('')
React.useEffect(() => {
const asd = async () => {
const user = data.item.userLogin.toLowerCase();
const response = await axios.get(
`https://api4.successfactors.com/odata/v2/Photo?$filter=tolower(userId) eq '${user}'`,
{
auth: {
username: 'Apiuser',
password: 'Apipass',
},
}
);
const encodedData = response.data.d.results[0].photo.toString();
console.log(encodedData);
setUri(encodedData);
};
asd()
}, [])
return (
...
<Avatar
source={{
uri: `data:image/png;base64,${uri}`,
}}
/>
)
}
Upvotes: 0