I have a RN/Expo project that, at times, returns a null value because the data just hasn't had the time to load.
The data is coming from an AWS server.
If I refresh the page, this will normally fix itself, however this is not a long term solution.
How can I modify this function so that it will run again, if, and only if, it returns a "null" response for any of the variables?
Below is my code:
const [ firstName, getFirstName ] = useState('')
const [ phone, getPhone ] = useState('')
const [ email, getEmail ] = useState('')
const [ userPhoto, getUserPhoto ] = useState(null)
useEffect(()=>{
const info_response = server_grab.get_user_info().then(response=>{
const displayName = async()=>{
getFirstName(
<Text style = {styles.title}>
{response.first_name} {response.last_name}
</Text>
)
getPhone(
<Text style = {styles.box_text}>
{response.phone}
</Text>
)
getEmail(
<Text style = {styles.box_text}>
{response.email}
</Text>
)
}
)
}
const displayPhoto = async () =>{
const photo_response = server_grab.download_profile_photo().then(response=>{
getUserPhoto(response.photo_data.raw_data)
}
)
}
displayPhoto()
displayName()
...
return(
<View>
{userPhoto && <Avatar.Image source= {{uri:`data:image/jpg;base64,${userPhoto}`}}/>}
</View>
<View>
<Text>{firstName}</Text>
<Text>{email}</Text>
<Text>{phone}</Text>
</View>
)
This is an example of the concept you could use:
import { Text, View, Image, ActivityIndicator } from 'react-native';
const simulateApiCall = (type, timeout = 1000 ) => new Promise((resolve, reject) => {
setTimeout(() => {
switch(type){
case "firstName":
resolve('John');
break;
case 'lastName':
resolve('Doe');
break;
case 'avatar':
resolve('https://cdn1.vectorstock.com/i/1000x1000/31/95/user-sign-icon-person-symbol-human-avatar-vector-12693195.jpg');
break;
}
}, timeout);
});
const Home = () => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [userAvatar, setUserAvatar] = useState(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
loadUserData();
}, [loadUserData]);
const loadUserData = useCallback(async () => {
setIsLoading(true);
try {
const userFirstName = await simulateApiCall('firstName');
const userLastName = await simulateApiCall('lastName');
setFirstName(userFirstName ?? '');
setLastName(userLastName ?? '');
setIsLoading(false);
loadUserAvatar();
} catch (error) {
setIsLoading(false);
console.log('Error loading user data');
}
}, [loadUserAvatar]);
const loadUserAvatar = useCallback(async () => {
try {
const userAvatar = await simulateApiCall('avatar', 2000);
setUserAvatar(userAvatar);
} catch(error){
console.log('Error loading user avatar')
}
}, []);
return(<View>
{isLoading ? <ActivityIndicator /> :
<>
{userAvatar && <Text>{userAvatar}</Text>}
<Text>{firstName}</Text>
<Text>{lastName}</Text>
</>
}
</View>);
}
export default Home;
You can play around here https://snack.expo.dev/@steppannws/d39758