React Native FlatList display - javascript

I'm using a flatlist with rowNumber={4} and I want to display some elements with a Width-max.
But I got this result :
As you can see some elements protrude on the left side. How can I make it fit automatically ?
Expected result :
There is my code :
<SafeAreaView>
<View
style={{
height: "100%",
maxWidth: "100%",
right: "10%",
}}
>
<FlatList
style={{width: "120%"}}
data={brands}
numColumns={4}
keyExtractor={(_, item) => item}
renderItem={({item}) => (
<View style={styles.card} key={item["id"]}>
<TouchableOpacity
onPress={() => {
var index = brandId.indexOf(item["id"]);
if (index > -1) {
brandId.splice(index, 1);
cpt = cpt - 1;
} else {
brandId.push(item["id"]);
cpt = cpt + 1;
}
console.log("ici ! ", cpt);
console.log("Il existe deja bro", brandId);
}}
>
<Text style={styles.text}>{item["name"]}</Text>
</TouchableOpacity>
</View>
)}
/>
</View>
</SafeAreaView>
CSS :
card: {
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
},
text: {
paddingRight: "2%",
textAlign: "center",
width: "100%",
fontSize: 12,
color: "black",
},

don't use flatlist. with flatlist you will always have fixed numberOfColumns but your item widths could be diff from each other. use map instead inside scrollview.
updated code :
<View style={[{ flexDirection: 'row', flexWrap: 'wrap' }]}>
{brands.map(element => {
return <View style={styles.card}>
<Text>{element.name}</Text>
</View>
})
}
</View>
styles:
card: {
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
paddingHorizontal: 5
},

Modify style of card:
card: {
flex:1,
flexDirection:"row"
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
},
or If you don't use flatlist then below code will solve your issue:
<View style={[{flexDirection: 'row', flexWrap: ' wrap'}]}>
data.map(element => {
return <Text style={{height:100}}>element.content</Text>
})
</View>

Related

How to list items with the same id in Async Storage in React Native

I'm new to React native, I'm creating a online store app my problem is : when the person selects a repeated item it does not appear in the cart it just updates , I would like it to include and list in the cart this repeated item ... as I said I'm new to react native, but I believe the problem is in the listing and not in the register ...
Function add in cart in AddCart.js
const addToCart = async (id) => {
let itemArray = await AsyncStorage.getItem('cartItems');
itemArray = JSON.parse(itemArray);
if (itemArray) {
let array = itemArray;
array.push(id);
try {
await AsyncStorage.setItem('cartItems', JSON.stringify(array));
ToastAndroid.show(
'Item Added Successfully to cart',
ToastAndroid.SHORT,
);
navigation.navigate('Home');
} catch (error) {
return error;
}
} else {
let array = [];
array.push(id);
try {
await AsyncStorage.setItem('cartItems', JSON.stringify(array));
ToastAndroid.show(
'Item Added Successfully to cart',
ToastAndroid.SHORT,
);
navigation.navigate('Home');
} catch (error) {
return error;
}
}
};
MyCart.js
import React, {useState, useEffect} from 'react';
import {
View,
Text,
TouchableOpacity,
Image,
Alert
} from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
const MyCart = ({navigation}) => {
const [product, setProduct] = useState();
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
getDataFromDB();
});
return unsubscribe;
}, [navigation]);
const getDataFromDB = async id =>{
let items = await AsyncStorage.getItem('cartItems');
items = JSON.parse(items);
if(items.length===0){
Alert.alert(
"Ops",
"The cart is empty",
[
{
text: "Ok",
onPress: () => navigation.navigate('Home'),
style: "cancel"
}
]
);
}else{
let productData = [];
if (items) {
Items.forEach(data => {
if (items.includes(data.id)) {
productData.push(data);
return;
}
});
setProduct(productData);
getTotal(productData);
} else {
setProduct(false);
getTotal(false);
}
}
};
const renderProducts = (data, index) => {
return (
<TouchableOpacity
key={data.key}
onPress={() => navigation.navigate('ProductInfo', {productID: data.id})}
style={{
width: '100%',
height: 100,
marginVertical: 6,
flexDirection: 'row',
alignItems: 'center',
}}>
<View
style={{
width: '30%',
height: 100,
padding: 14,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: COLOURS.backgroundLight,
borderRadius: 10,
marginRight: 22,
}}>
<Image
source={data.productImage}
style={{
width: '100%',
height: '100%',
resizeMode: 'contain',
}}
/>
</View>
<View
style={{
flex: 1,
height: '100%',
justifyContent: 'space-around',
}}>
<View style={{}}>
<Text
style={{
fontSize: 14,
maxWidth: '100%',
color: COLOURS.black,
fontWeight: '600',
letterSpacing: 1,
}}>
{data.productName},
</Text>
<View
style={{
marginTop: 4,
flexDirection: 'row',
alignItems: 'center',
opacity: 0.6,
}}>
<Text
style={{
fontSize: 14,
fontWeight: '400',
maxWidth: '85%',
marginRight: 4,
}}>
R$ {data.productPrice2}.00 , {data.id}
</Text>
<Text>
</Text>
</View>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
<View
style={{
borderRadius: 100,
marginRight: 20,
padding: 4,
borderWidth: 1,
borderColor: COLOURS.backgroundMedium,
opacity: 0.5,
}}>
<MaterialCommunityIcons
name="minus"
style={{
fontSize: 16,
color: COLOURS.backgroundDark,
}}
/>
</View>
<Text>1</Text>
<View
style={{
borderRadius: 100,
marginLeft: 20,
padding: 4,
borderWidth: 1,
borderColor: COLOURS.backgroundMedium,
opacity: 0.5,
}}>
<MaterialCommunityIcons
name="plus"
style={{
fontSize: 16,
color: COLOURS.backgroundDark,
}}
/>
</View>
</View>
<TouchableOpacity onPress={() => removeItemFromCart(data.id)}>
<MaterialCommunityIcons
name="delete-outline"
style={{
fontSize: 16,
color: COLOURS.backgroundDark,
backgroundColor: COLOURS.backgroundLight,
padding: 8,
borderRadius: 100,
}}
/>
</TouchableOpacity>
</View>
</View>
</TouchableOpacity>
);
};
return (
<View> {product ? product.map(renderProducts) : null} </View>
);
};
export default MyCart;
I would be grateful to help me

Center element horizontally in React Native

I want to center a button horizontally, this is my code:
return (
<View style={styles.root}>
<View style={styles.container}>
<SafeAreaView style={HEADER}>
<SliderBox
style={{ height: '100%' }}
currentImageEmitter={index => setCurrentSliderNumber(index)}
images={data.images}>
</SliderBox>
</SafeAreaView>
{currentSliderNumber == data.images.length - 1 ? <View style={styles.item}>
<Button
style={styles.getStartedButton}
appearance="ghost"
status="control"
onPress={onGetStartedPressed}
>
Get Started
</Button>
</View> : null}
</View>
</View>
)
and this is my styling:
const styles = StyleSheet.create({
forgotPasswordButton: {
paddingHorizontal: 0,
},
root: {
flex: 1,
height: '100%',
backgroundColor: '#fff'
},
container: {
borderColor: 'rgba(0,0,0,0.2)',
},
getStartedButton: {
marginVertical: 12,
backgroundColor: 'red'
},
item: {
borderColor: 'rgba(0,0,0,0.2)',
position: 'absolute',
top: '80%',
left: '50%'
}, text: {
position: 'absolute',
top: '30%',
left: '10%'
}
})
I also tried to add alingnItems:center to root:
root: {
flex: 1,
height: '100%',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
But the result is not the one expected:
Try changing the item style object to this:
item: {
borderColor: 'rgba(0,0,0,0.2)',
position: 'absolute',
top: '80%',
left:0,
width:"100%",
alignItems:"center",
justifyContent:"center"
},
Do not use position until it's necessary you should use flex properties.
return (
<View style={styles.root}>
<View style={styles.container}>
<SafeAreaView style={HEADER}>
<SliderBox
style={{ height: '100%' }}
currentImageEmitter={index => setCurrentSliderNumber(index)}
images={data.images}>
</SliderBox>
</SafeAreaView>
{currentSliderNumber == data.images.length - 1 ? <View style={styles.item}>
<Button
style={styles.getStartedButton}
appearance="ghost"
status="control"
onPress={onGetStartedPressed}
>
Get Started
</Button>
</View> : null}
</View>
</View>
)
Styles
const styles = StyleSheet.create({
forgotPasswordButton: {
paddingHorizontal: 0,
},
root: {
flex: 1,
height: '100%',
backgroundColor: '#fff'
},
container: {
borderColor: 'rgba(0,0,0,0.2)',
flexGrow:1,
justifyContent: "space-between"
},
getStartedButton: {
marginVertical: 12,
backgroundColor: 'red',
alignSelf:"center",
flexGrow:2,
},
item: {
borderColor: 'rgba(0,0,0,0.2)',
flexGrow:1,
justifyContent:"center",
alignItem:"center",
}, text: {
}
})
Check out the layout docs

ERROR : undefined is not an object (evaluation 'style.width')

Hello everyone I'm having trouble with component and I get an undefined error message.So my app has 2 screen,the first one has a list of imagebackgrounds and when you press on one of the images you get a description of that image on another screen.So on this second screen I get the image that I pressed on in an image component (not background).
The problem I'm having is that when I save I get the undefined error.
First screen component :
const MealItems = (props) => {
return (
<View style={styles.main}>
<TouchableOpacity onPress={props.onSelectMeal}>
<View>
<View style={{ ...styles.details, ...styles.maintitle }}>
<ImageBackground
//resizeMode={"center"}
source={{ uri: props.image }}
style={styles.imagebg}
>
<View style={styles.textContainer}>
<Text style={styles.title} numberOfLines={1}>
{props.title}
</Text>
</View>
</ImageBackground>
</View>
<View style={{ ...styles.details, ...styles.info }}>
<Text>{props.duration}</Text>
<Text>{props.complexity.toUpperCase()}</Text>
<Text>{props.affordability.toUpperCase()}</Text>
</View>
</View>
</TouchableOpacity>
</View>
);
};
styles = StyleSheet.create({
main: {
height: 200,
width: "100%",
backgroundColor: "#f5f5f5",
borderRadius: 20,
overflow: "hidden",
marginVertical: 10,
},
maintitle: {
height: "85%",
},
title: {
fontSize: 20,
color: "white",
textAlign: "center",
},
details: {
flexDirection: "row",
},
imagebg: {
width: "100%",
height: "100%",
},
info: {
backgroundColor: "gray",
paddingHorizontal: 10,
justifyContent: "space-between",
alignItems: "center",
height: "15%",
},
textContainer: {
paddingHorizontal: 12,
paddingVertical: 10,
backgroundColor: "rgba(0,0,0,0.3)",
},
});
export default MealItems;
***Second screen file:***
const howToCook = (props) => {
const availableMeals = useSelector((state) => state.Meals.filteredMeals);
const mealId = props.navigation.getParam("mealId");
const selectedMeal = availableMeals.find((meal) => mealId === meal.id);
return (
<ScrollView>
<Image source={{ uri: selectedMeal.imageUrl }} style={styles.image} />
<View style={styles.textDetail}>
<Text>{selectedMeal.duration}</Text>
<Text>{selectedMeal.complexity.toUpperCase()}</Text>
<Text>{selectedMeal.affordability.toUpperCase()}</Text>
</View>
<View style={styles.titlePlace}>
<Text style={styles.textTitle}>Ingredients</Text>
</View>

FlatList RefreshControl not working on Android

I have a FlatList inside of a view and I'm unable to get the refresh control working on Android emulators/devices.
I have tried many solutions but to no luck. Any help or suggestions would be greatly appreciated.
Code:
onPullToRefresh = () => {
this.props.onRefreshData();
}
...
render() {
const isRefreshing = this.props.refreshing['entities'] ? this.props.refreshing['entities'] : false;
...
{!this.state.favoritesExpand &&
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<FlatListCustom
style={{ flex: 1, flexDirection: 'column' }}
data={this.state.searchString && this.state.searchString.length > 0 ? this.state.searchMatchedItems : this.state.items}
renderItem={this.renderEntityItem}
keyExtractor={(item) => item.id}
extractData={this.state.selectedItemId}
windowSize={1}
ref={ref => this.itemScrollViewRef = ref}
getItemLayout={this.getItemLayout}
refreshControl={
<RefreshControl refreshing={isRefreshing} onRefresh={this.onPullToRefresh} />
}
/>
{(screenMaster == 'investor' || screenMaster == 'asset') &&
<View style={{ position: 'absolute', right: 0, top: 0, justifyContent: 'space-between', flex: 1, flexDirection: 'column', height: '100%', paddingTop: 8, paddingBottom: 20 }}>
{this.state.AZList.map(item => (
<Touch
key={`AZList_${item}`}
onPress={() => this.onAZListSelect(item)}
>
<Text style={{ textAlign: 'center', color: '#006dc4', fontSize: Platform.isPad ? normalize(7) : normalize(12), paddingHorizontal: 10, fontWeight: 'bold', fontFamily: "Geogrotesque" }}>{item}</Text>
</Touch>
))}
</View>
}
</View>
}

React Native parent view size is changing when adding a child view

I have a settings for language selection in my app. As you can see below, when I choose another language, the row height of the selected language is increasing a little bit. I would like to keep it fixed, and choosing a language should not have an effect on the row height. How can I achieve this?
<FlatList
data={availableLanguages}
ItemSeparatorComponent={this.renderSeparator}
renderItem={({ item }) => {
return (
<TouchableOpacity onPress={() => this.onChangeLang(item)}>
<View style={styles.flatlistItem} >
<Text style={styles.languageListitem} >{t('settings:' + item)}</Text>
{appLanguage === item ? <View style={styles.listIconRightEnd}><CheckActiveLightMode width={25} /></View> : null}
</View>
</TouchableOpacity>
)
}}
keyExtractor={(item, index) => index}
/>
Styles:
flatlistItem: {
margin: 4,
paddingLeft: 10,
paddingVertical: 7,
backgroundColor: '#FFF',
width: '100%',
flex: 1,
alignSelf: 'center',
flexDirection: 'row',
borderRadius: 0,
},
languageListitem: {
color: 'rgb(48,49,147)',
fontSize: 16,
paddingLeft: 10,
flex: 1,
},
listIconRightEnd: {
paddingRight: 20,
},
Solved with maxHeight:
listIconRightEnd: {
paddingRight: 20,
maxHeight: 10,
},

Categories

Resources