How to display posted data without refresh screen in React Native? - javascript

I have a screen that takes care of creating a garden, I have another screen that is used to display the garden (therefore its name, its image, etc.).
So in my first screen which is used to create the garden I make a post request to create it as you can see below. And in my second screen I call my API by making a GET request to retrieve the data from the garden I just created.
But the problem is that I have to constantly reload the application to see the garden appear... How can I ensure that with each new creation the garden state is updated with the new data that has just appeared?
Here is the code of first screen (POST request) :
export default function FormCreateGarden({navigation}) {
const [loading, setLoading] = useState(false);
const [user, setUser] = useState({});
const [garden, setGarden] = useState(false);
const [gardenName, setGardenName] = useState('');
const [gardenImage, setGardenImage] = useState({uri: '', type: '', name: ''});
const [isVisible, setIsVisible] = useState(false);
const baseUrl = 'http://127.0.0.1/api';
const submitButton = async () => {
if (!gardenName.trim()) {
alert("Veuillez renter un nom de jardin s'il vous plait!");
return;
}
setLoading(true);
try {
const jsonValue = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(jsonValue) || {};
setUser(parsedUserData);
const myHeaders = new Headers();
myHeaders.append('Authorization', `Token ${parsedUserData.token}`);
const photo = {
uri: gardenImage.uri,
type: gardenImage.type,
name: gardenImage.name,
};
const formdata = new FormData();
formdata.append('name', gardenName);
formdata.append('user', parsedUserData.user.id);
formdata.append('image', photo);
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow',
};
const response = await fetch(`${baseUrl}/garden/`, requestOptions);
if (response.status === 201) {
let data = await response.json();
alert(`Votre jardin "${gardenName}" a bien été crée`);
setLoading(false);
setGardenName('');
setGardenImage({uri: '', type: '', name: ''});
navigation.navigate('GardenHome');
} else {
throw new Error('Erreur');
}
} catch (e) {
setLoading(false);
console.log(e.message);
console.log(e);
}
};
return (
<View style={styles.container}>
<View>
<Text>
Créez votre jardin :
</Text>
<View>
<Text>Nom de votre jardin :</Text>
<TextInput
placeholder="Mon jardin"
placeholderTextColor={'gray'}
onChangeText={text => setGardenName(text)}
value={gardenName}
/>
</View>
<View>
<Text>Ajouter une photo</Text>
{gardenImage.uri === '' ? (
<TouchableWithoutFeedback onPress={() => setIsVisible(true)}>
<View>
<FontAwesomeIcon
icon={faCamera}
size={30}
/>
</View>
</TouchableWithoutFeedback>
) : (
<Image
source={{uri: gardenImage.uri}}
/>
)}
<BottomSheet modalProps={{}} isVisible={isVisible}>
{list.map((l, i) => (
<ListItem
key={i}
containerStyle={l.containerStyle}
onPress={l.onPress}>
<ListItem.Content>
<ListItem.Title style={l.titleStyle}>
{l.title}
</ListItem.Title>
</ListItem.Content>
</ListItem>
))}
</BottomSheet>
</View>
<View>
<View>
<Button
title="Annuler"
color={'black'}
onPress={cancelButton}
/>
</View>
<View>
<Button
title="Valider"
color={'white'}
onPress={submitButton}
/>
</View>
</View>
</View>
);
}
Here is the code of second screen (GET request) :
export default function GardenHome() {
const [garden, setGarden] = useState([]);
const [loading, setLoading] = useState(false);
const navigation = useNavigation();
const gardenData = async () => {
setLoading(true);
const user = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(user);
try {
const response = await axios.get(
`http://127.0.0.1/api/garden?user=${parsedUserData.user.id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (response.status === 200) {
setGarden(response.data);
setLoading(false);
}
} catch (e) {
console.log('Erreur ' + e);
setLoading(false);
}
};
useEffect(() => {
gardenData();
}, []);
const gardenJSX = garden.map(item => {
return (
<View style={{flex: 0.75}} key={item.id}>
<Image
source={{uri: item.image}}
style={{marginTop: 15, width: '100%', height: 150}}
/>
<View>
<View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
}}>
</View>
</View>
</View>
);
});
if (loading) {
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<ActivityIndicator size="large" color="#3c693d" />
</View>
);
} else {
return (
<View style={styles.container}>
<Heading name="Jardin de" />
<View style={styles.content}>
<View style={{height: '65%'}}>
<ScrollView>{gardenJSX}</ScrollView>
</View>
<HerbGarden />
</View>
</View>
);
}
}
Thanks for help !

Related

React native State update on pressing a button

I am trying to update my full screen on pressing a button. I have tried updating States but is not working for my case. I don't know if its causing for the async function or not.
This is my states:
const [bNumber, setBNumber] = React.useState('');
const [rollNumWeight, setRollNumWeight] = useState([]);
const [rollNumber, setRollNumber] = useState('');
const [rollWeight, setRollWeight] = useState('');
Bellow is function I am using:
const saveRoll = async () => {
try {
const response = await fetch('someURL', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
roll_num_weight: rollNumWeight,
bNumber: bNumber
})
});
const json = await response.json();
setBNumber('')
setRollNumber('')
setRollWeight('')
setRollNumWeight([])
AlertButton('Rolls Saved Successfully!')
} catch (error) {
console.error(error);
}
}
I am inputting some data on this stage so my states changes from initial state. Then I am pressing SAVE button
This is the button I am calling my function from:
<TouchableOpacity style={styles.button} onPress={saveRoll}>
<Text style={styles.buttonText}>Save</Text>
</TouchableOpacity>
After Pressing the save button it nothing changes. All the states remain the same.
Bellow is my full render code:
<View style={styles.container}>
<ScrollView
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}>
<View style={styles.app}>
<View style={styles.col1}>
<Text>WORKORDER/BATCHNO</Text>
<SelectDropdown
data={batches}
onSelect={(selectedItem) => {
// getData(selectedItem)
setBNumber(selectedItem)
}}
defaultButtonText={'Select Batch NO'}
buttonTextAfterSelection={(selectedItem, index) => {
return selectedItem;
}}
rowTextForSelection={(item, index) => {
return item;
}}
buttonStyle={styles.input}
buttonTextStyle={styles.dropdown1BtnTxtStyle}
renderDropdownIcon={isOpened => {
return <FontAwesome name={isOpened ? 'chevron-up' : 'chevron-down'} color={'#444'} size={18} />;
}}
dropdownIconPosition={'right'}
dropdownStyle={styles.dropdown1DropdownStyle}
rowStyle={styles.dropdown1RowStyle}
rowTextStyle={styles.dropdown1RowTxtStyle}
selectedRowStyle={styles.dropdown1SelectedRowStyle}
search
searchInputStyle={styles.dropdown1searchInputStyleStyle}
searchPlaceHolder={'Search here'}
searchPlaceHolderColor={'darkgrey'}
renderSearchInputLeftIcon={() => {
return <FontAwesome name={'search'} color={'#444'} size={18} />;
}}
/>
</View>
<View pointerEvents="none">
</View>
<View style={styles.row}>
<View style={styles.col1}>
<Text>Roll Number</Text>
<TextInput
placeholder='Roll Number'
keyboardType='numeric'
style={styles.input}
value={rollNumber}
onChangeText={(val) => setRollNumber(val)} />
</View>
<View style={styles.col1}>
<Text>Roll Weight</Text>
<TextInput
placeholder='Roll Weight'
keyboardType='numeric'
style={styles.input}
value={rollWeight}
onChangeText={(val) => setRollWeight(val)} />
</View>
</View>
<Button title=' Add ' onPress={addRoll}></Button>
</View>
<TouchableOpacity style={styles.button} onPress={saveRoll}>
<Text style={styles.buttonText}>Save</Text>
</TouchableOpacity>
<Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff'}}>
<Row data={tableHead} style={styles.head} textStyle={styles.text}/>
<Rows data={rollNumWeight} textStyle={styles.text}/>
</Table>
</ScrollView>
</View>
);

TypeError: Cannot read property 's_path' of undefined (React Native)

How to solve this issue ?
i'm new in React Native, i'm try to solve this issue last 2 days.
TypeError: Cannot read property 's_path' of undefined
This error is located at:
in List (at SearchScreen.js:119)
I'm try to get images from server
I have searched a lot, but couldn't solve it. Please help.
SearchPage.js
useEffect(() => {
loadItem();
}, [query, pageCurrent, refreshing]);
const loadItem = async () => {
const response = await client.get(
`api.php?key=test-api-key&type=read&object=search&action=latestItems&limit=${pageCurrent}`
);
if (!response.ok) return setError(true);
setError(false);
setRefreshing(false);
dispatch(adDeatailsRequiested());
dispatch(adsData(response.data.response));
};
handleSearch = (text) => {
setQuery(text);
dispatch(searchQuery(query1));
};
loadMore = () => {
setpageCurrent(pageCurrent + 10);
};
pageRefreshing = () => {
setRefreshing(true);
};
return (
<View style={styles.container}>
<ActivityIndicator visible={loading} />
<View style={styles.listing}>
<FlatList
showsVerticalScrollIndicator={false}
numColumns={!liked ? 1 : 2}
key={!liked ? "ONE COLUMN" : "TWO COLUMN"}
style={styles.list}
data={Data}
keyExtractor={(item) => item.pk_i_id}
initialNumToRender={10}
removeClippedSubviews={true}
onEndReached={loadMore}
onEndReachedThreshold={0}
refreshing={refreshing}
onRefresh={pageRefreshing}
renderItem={({ item }) => (
LINE 119=>>>>> <List
title={item.s_title}
description={item.s_description}
subTitle={"₹" + item.i_price}
location={item.s_city}
region={item.s_region}
date={item.dt_pub_date}
adId={item.fk_i_item_id}
onPress={() =>
navigation.navigate(
routes.ITEM_SCREEN,
{
itemId: item.fk_i_item_id,
title: item.s_title,
description: item.s_description,
price: item.i_price,
date: item.dt_pub_date,
region: item.s_region,
city: item.s_city,
userName: item.s_contact_name,
userId: item.fk_i_user_id,
}
)
}
/>
)}
</>
)}
/>
</View>
</View>
);
}
list.js
useEffect(() => {
loadImage();
}, []);
const loadImage = async () => {
const response = await itemApi.getImage(+adId);
if (!response.ok) return setError(true);
setError(false);
setImage(response.data.response);
};
return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={styles.container}>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={
image
? {
uri: `${baseURL}${image[0].s_path}${image[0].pk_i_id}.${image[0].s_extension}`,
}
: defaultImg
}
/>
</View>
</View>
</TouchableWithoutFeedback>
);
Please add condition to check that image[0] is not null or undefined like that
{image[0] &&
<Image
style={styles.image}
source={
image
? {
uri: `${baseURL}${image[0].s_path}${image[0].pk_i_id}.${image[0].s_extension}`,
}
: defaultImg
}
/>}

react-native how do I show activityindicator while file uploading

I want to have a loading spinner appear in the middle of the screen while the file is being uploaded.
The clicked file is loaded and appears in the file list as well.
I imported ActivityIndicator from 'react-native'.
When I wrote the code after as a test, the loading spinner was well seen.
However, I wanted to make the spinner appear only the file is loaded. So, I wrote the code, but the loading spinner does not appear.
import {Text,View,ImageBackground,Image,StyleSheet,TouchableOpacity,FlatList,Button,ActivityIndicator} from 'react-native';
export default function FileUpload({route, navigation}) {
const [multipleFile, setMF] = useState([])
const [isLoading, setLoading] = useState(true);
useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 5000);
}, [])
const addEntry = (data) => {
let newObj = {
"id": randId(),
"name" : data.filename,
"text" : data.text,
}
console.log('Finish load');
setMF([...multipleFile, newObj]);
console.log(multipleFile)
};
const randId = () => {
let id = ''
for (var i = 0; i < 10; i++) {
id += String.fromCharCode(Math.trunc(Math.random()*85) + 48)
}
return id
}
const sendFile = () => {
axios({
method: 'post',
url: '',
data: {
"uri": ""
}
}).then((res) =>{
addEntry(res.data)
}
).catch((err) => console.log(err));
}
const renderItem = ({ item }) => (
<Text>{item.name}</Text>
);
return (
<ImageBackground source={require('../images/bg2.png')}
style={{width: '100%', height: '100%'}}>
<View>
<TouchableOpacity onPress={() => {
DocumentPicker.getDocumentAsync().then((res) => {
console.log(res)
if (res.type == 'success') {
console.log('load start');
if(isLoading){
return(
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large"/>
</View>
);
}
sendFile()
} else {
console.log('you cancelled')
}
})
}}
style={{alignItems: 'center'}}>
<Image source ={require('../images/cloud.png')}
style={styles.image}
/>
<View style={styles.viewTextStyle}>
<Text style={styles.textStyle}>{'Upload Files'} </Text>
<Text style={{fontSize:60, color:'white'}}> + </Text>
<Text style={styles.textStyle1}>{'Browse and select your file \n you want to upload'}</Text>
</View>
</TouchableOpacity>
</View>
<View style={styles.listHeader}>
<Text style={{textAlign: 'center', fontSize: 18}}> File List </Text>
</View>
<FlatList
style={styles.scrollContainer}
data={multipleFile}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}>
</FlatList>
{/* <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large"/>
</View> */}
<TouchableOpacity onPress={() => {
// console.log(multipleFile[0].name)
navigation.navigate('Details Search',
multipleFile[0]
)}}>
<View style={styles.button}>
<Text style={styles.buttonText}>Next</Text>
</View>
</TouchableOpacity>
</ImageBackground>
);
}
set the default state to false
const [isLoading, setLoading] = useState(false);
remove this effect
useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 5000);
}, [])
remove loading view from DocumentPicker.getDocumentAsync()
if (res.type == 'success') {
sendFile()
} else {
console.log('you cancelled')
}
set loading true/false in sendFile()
const sendFile = () => {
setLoading(true);
axios({
method: 'post',
url: '',
data: {
"uri": ""
}
}).then((res) =>{
setLoading(false)
addEntry(res.data)
}
).catch((err) => setLoading(false));
}
const renderItem = ({ item }) => (
<Text>{item.name}</Text>
);
add loading view in main return
return (
....
if(isLoading){
return(
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large"/>
</View>
);
}
....
)

React Navigation 5, CustomDrawer, Can't perform a React state update on context changed

on App.js, im using useContext to check of user logged in to switch active navigation,
Then, on Login screen after successful login, I got error "Can't perform a React state update on LoginScreen" after the context has changed.
I'm pretty sure it comes from Drawer, because when i try to logout and login back, the drawer opened immediately. but i didn't use any useState to handle login or logout, all my async function only used when handling login or logout not in useState.
you can find my sample video here:
https://vimeo.com/user125707637/review/471649007/2c9dd00d1a
you can see on the video, the drawer opened automatically after the error comes out. each time you login back, the drawer was open and need to close manually. Any idea? or it's a bug.. idk
App.js:
const App = ({navigation, route}) => {
const [user, setUser] = useState();
const [loadingVisible, setLoadingVisible] = useState(true);
const restoreAuth = async () => {
try {
const response = await userApi.getUser();
setUser(response.data);
onFinishLoad();
} catch (error) {
if (error.response.status === 401) {
return onFinishLoad();
}
await storage.removeToken();
setUser(null);
onFinishLoad();
}
};
const onFinishLoad = async () => {
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
await delay(500);
setLoadingVisible(false);
};
useEffect(() => {
let mounted = true;
if (mounted) {
restoreAuth();
}
return () => (mounted = false);
}, []);
return (
<StyleProvider style={getTheme(material)}>
<AuthContext.Provider value={{user, setUser}}>
<LoadingComponent visible={loadingVisible} />
<Container>
<NavigationContainer>
{user ? <AppDrawerNavigation /> : <AuthNavigation />} // checking context changes
</NavigationContainer>
</Container>
</AuthContext.Provider>
</StyleProvider>
);
};
export default App;
Auth Navigator:
const AuthNavigation = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Navigator>
);
};
LoginScreen:
const LoginScreen = ({navigation}) => {
const {user, setUser} = useContext(AuthContext);
const [loadingVisible, setLoadingVisible] = useState(false);
const validationSchema = Yup.object().shape({
email: Yup.string().required().label('E-mail'),
password: Yup.string().required().min(6).label('Password'),
});
const handleSubmit = async ({email, password}, actions) => {
setLoadingVisible(true);
try {
const response = await authApi.login(email, password, 'mobile');
storage.storeToken(response.data.token);
setUser(response.data.user);
setLoadingVisible(false);
} catch (error) {
const statusCode = error.response.status;
const errors = error.response.data;
const fieldErrors = errors?.errors;
const errorMessage = errors?.message;
setLoadingVisible(false);
if (statusCode === 422) {
for (let field in fieldErrors) {
actions.setFieldError(field, fieldErrors[field][0]);
}
} else {
Alert.alert(
'Login Failed',
`${errorMessage}`,
[{text: 'Ok', onPress: () => console.log('ok')}],
{cancelable: false},
);
}
}
};
return (
<Container>
<LoadingComponent visible={loadingVisible} />
<Content padder>
<View>
<Form
initialValues={{
email: '',
password: '',
}}
onSubmit={handleSubmit}
validationSchema={validationSchema}>
<FormField
name="email"
placeholder="E-mail"
keyboardType="email-address"
autoCorrect={false}
/>
<FormField
name="password"
autoCapitalize="none"
autoCorrect={false}
placeholder="Password"
secureTextEntry={true}
/>
<SubmitButton title="LOGIN" />
</Form>
<View style={{marginTop: 20}}>
<Text
style={{
flex: 1,
textAlign: 'center',
textDecorationLine: 'underline',
marginBottom: 10,
}}
onPress={() => navigation.navigate('Register')}>
Create an account
</Text>
<Text
style={{
flex: 1,
textAlign: 'center',
textDecorationLine: 'underline',
}}
onPress={() => navigation.navigate('ForgotPassword')}>
Forgot Password?
</Text>
</View>
</View>
</Content>
</Container>
);
};
Drawer Navigator:
const AppDrawerNavigation = () => {
return (
<Drawer.Navigator
initialRouteName="HomeStack"
drawerContentOptions={{
activeBackgroundColor: colors.primary,
activeTintColor: colors.light,
}}
drawerContent={(props) => <DrawerContent {...props} />}> // Render my custom Drawer
<Drawer.Screen
name="HomeStack"
component={HomeStackNavigation}
options={{
drawerLabel: ({color, focused}) => (
<Text style={{fontSize: !focused ? 14 : 16, color: color}}>
Entries
</Text>
),
drawerIcon: ({color, size, focused}) => (
<AntDesign
name="home"
color={color}
size={!focused ? size : size + 2}
/>
),
}}
/>
</Drawer.Navigator>
);
DrawerContent:
export const DrawerContent = (props) => {
const {user, setUser} = useContext(AuthContext);
const [loadingVisible, setLoadingVisible] = useState(false);
const handleLogout = () => {
Alert.alert(
null,
'Are you sure to logout?',
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{
text: 'OK',
onPress: _logout,
},
],
{cancelable: false},
);
};
//handling logout
const _logout = async () => {
props.navigation.closeDrawer();
setLoadingVisible(true);
try {
const response = await authApi.logout();
await storage.removeToken();
setUser(null); // set user context to null
setLoadingVisible(false);
} catch (error) {
setLoadingVisible(false);
Alert.alert(
'Error',
'Failed to logout',
[
{
text: 'OK',
onPress: console.log('ok'),
},
],
{cancelable: false},
);
}
};
return (
<View style={{flex: 1}}>
<LoadingComponent visible={loadingVisible} />
<DrawerContentScrollView {...props}>
<View style={styles.drawerContent}>
<View style={styles.userInfoSection}>
<View style={{paddingVertical: 20}}>
<Text style={{fontSize: 28}}>SMART</Text>
<Text style={{fontSize: 16}}>Incident Management System</Text>
</View>
</View>
<Drawer.Section style={styles.drawerSection}>
<DrawerItemList {...props} />
</Drawer.Section>
</View>
</DrawerContentScrollView>
<Drawer.Section style={styles.bottomDrawerSection}>
<DrawerItem
icon={({color, size}) => (
<AntDesign name="logout" color={color} size={size} />
)}
label="Sign Out"
onPress={handleLogout}
/>
</Drawer.Section>
</View>
);
};

too many rerenders on using useState

I am calling the contactsfunction from the main return. I don't see any error until here:
const showContacts = React.useCallback(
(data: UsersQueryHookResult) => {
if (data) {
return (
<View style={styles.users}>
</View>
);
}
},
[userData],
);
const contacts = () => {
console.log('running');
const { loading, error, data } = useUsersQuery({
variables: {
where: { id: 34 },
},
});
console.log('DATA COMING', data);
//setUserData(data);
//console.log('contact name', data.users.nodes[0].userRelations[0].relatedUser.firstName);
};
return (
<SafeAreaView style={{ flex: 1 }}>
<Container style={{ flex: 1, alignItems: 'center' }}>
<Item style={styles.addToWhitelist}>
<Icon
name="add"
onPress={() => navigation.navigate('AddContactTry')}
/>
<Text style={styles.addToContactTitle}>Add contact</Text>
</Item>
<Text onPress={() => navigation.navigate('Home')}>Zurück</Text>
<View style={{ width: moderateScale(350) }}>
<Text>Keine Kontacte</Text>
</View>
{contacts()}
</Container>
</SafeAreaView>
);
};
Now I want to do some conditional rendering on the basis of the results from contacts. However, as soon as I uncomment setUserData(data); I get an error that too many re-renders. I don't get what I am doing wrong in showUsersto get this error.
Edit:
I tried this but it gives an invalid hook call error:
export const Whitelist: React.FunctionComponent = (props) => {
const [userData, setUserData] = useState<UsersQueryHookResult>('');
useEffect(() => {
// Your function to fetch/get contacts
const data = contacts();
setUserData(data);
}, [])
const showContacts = React.useCallback(
(data: UsersQueryHookResult) => {
if (data) {
return (
<View style={styles.users}>
</View>
);
}
},
[userData],
);
const contacts = () => {
console.log('running');
const { loading, error, data } = useUsersQuery({
variables: {
where: { id: 34 },
},
});
console.log('DATA COMING', data);
//setUserData(data);
};
return (
<SafeAreaView style={{ flex: 1 }}>
<Container style={{ flex: 1, alignItems: 'center' }}>
<Item style={styles.addToWhitelist}>
<Icon
name="add"
onPress={() => navigation.navigate('AddContactTry')}
/>
<Text style={styles.addToContactTitle}>Add contact</Text>
</Item>
<Text onPress={() => navigation.navigate('Home')}>Zurück</Text>
{/* {contacts()} */}
</Container>
</SafeAreaView>
);
};
Try to fetch contacts in componentDidMount method or useEffect (in your case with hooks) and store the result in a state with useState.
const [contacts, setContacts] = React.useState(null);
[...]
React.useEffect(() => {
// Your function to fetch/get contacts
const data = contacts();
setContacts(data);
}, [])
[...]
return (
<SafeAreaView style={{ flex: 1 }}>
[...]
{contacts && contacts.map(contact => (<View>{contact.name}</View>)}
[...]
</SafeAreaView>
);
hope it helps.

Categories