React-native conditional render is affecting elements outside the condition - reactjs

I am attempting to conditionally render an icon and some text if the user has connection via wifi or cell data. The icon on the very left with the phone number should only appear if there is a connection. Otherwise, it should not render, and the rest of the icons should fill the space. When I toggle connectivity, the phone number text remains, but the icon disappears and the rest of them fill the space as they should. Can anyone tell me why the text (the phone number) is not changing as desired?
Relevant code for conditional render:
<View style={styles.actionArea}>
{props.isConnected && (
<View style={styles.actionItem}>
<Text>{props.dispatch.call_back_number}</Text>
<MaterialCommunityIcons name={'phone-forward'} size={50} onPress={() => handleClick(`tel:${props.dispatch.call_back_number}`)}/>
</View>
)}
<View style={styles.actionItem}>
<Text>Enter Call Log</Text>
<MaterialCommunityIcons name={'phone'} size={50} onPress={() => props.enterCallLog(true)}/>
</View>
<View style={styles.actionItem}>
<Text>Work Order</Text>
<MaterialCommunityIcons name={'wrench'} size={50}/>
</View>
<View style={styles.actionItem}>
<Text>Contracts</Text>
<MaterialCommunityIcons name={'animation'} size={50}/>
</View>
</View>
The styles code:
actionArea: {
paddingTop: 10,
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
},
actionItem: {
flexDirection: 'column',
alignItems: 'center',
},

Related

How to make the ProgressBar occupy the remaining width of the View container

What I want to achieve:
I want a horizontal view with two elements:
Text
ProgressBar (imported from React Native Paper)
I want the text to take as much space as needed (fit-content). The rest of the width should be taken by the ProgressBar.
What I've tried so far:
<View style={{
flexDirection: 'row',
alignItems: 'center'
}}>
<Text>Difficulty:</Text>
<ProgressBar
progress={0.2}
color="#5E84E2"
/>
</View>
With the above setup, the ProgressBar is not even visible. What am I doing wrong?
You can give flex:1 to progress bar view to fit in remaining space
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
<View>
<Text>Difficulty:</Text>
</View>
<View style={{ flex: 1 }}>
<ProgressBar progress={0.5} color="red" />
</View>
</View>
Preview : https://snack.expo.dev/Ef39fDbCK

React Native alignItems is not working properly in the View

As you see the picture attached, I set the align item as center with the icon and text. However, I do not know why the icon is not aligned. Do you have any idea?
...
<View style={styles.nameElement}>
<TouchableOpacity>
<MaterialCommunityIcons name="calendar" size={26} />
<Text>Calendar</Text>
{/* <MaterialCommunityIcons name="calendar-alert" size={26} /> */}
</TouchableOpacity>
</View>
...
const styles = StyleSheet.create({
...
nameElement: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
...
})
Because you only set the alignItem and justifyContent style for the <View> component which is not your icon and text container in your case.
So your must set <TouchableOpacity style={{alignItems: 'center'}}>
try this
<View style={styles.nameElement}>
<TouchableOpacity style={{alignItems: "center",
justifyContent: "center",}}>
<MaterialCommunityIcons name="calendar" size={26} />
<Text>Calendar</Text>
{/* <MaterialCommunityIcons name="calendar-alert" size={26} /> */}
</TouchableOpacity>
</View>

ReactNative Text Style Next Line

Simply I am trying to make 3 Texts with icons align in a column
I want to give the expo icons a little margin-top so they are next to each text element
Then how can I make the next line in text aligned with the text itself
For Example The (S) in School to be vertically aligned with the (5) in 5th
I searched a lot on how to do that in react-native but with no luck
and I tried some normal CSS stuff but didn't work is it achievable?
Code :
<View style={styles.cardView}>
<Text style={styles.CardTextLayout} > <MaterialIcons name="store" size={21} color="lightgrey" /> {item.key} </Text>
<Text style={styles.locationText} > <Entypo name="location-pin" size={21} color="lightgrey" />5th Settelment, Near Akhnaton School, Cairo</Text>
<Text style={styles.locationText} > <MaterialIcons name="description" size={21} color="lightgrey" />Breif Description about the place and what is offers</Text>
</View>
Styles
CardTextLayout: {
// marginLeft: 8,
fontSize: cardResponsiveFontSize,
fontWeight: 'bold',
textAlign: 'left',
color: '#231F20',
elevation: 8,
},
locationText: {
fontSize: cardResponsiveFontSize,
textAlign: 'left',
color: '#231F20',
elevation: 8,
},
I don't know how you would do that with your current code, but you can try to set it up like this.
<View style={styles.cardView}>
<View style={styles.cardRow}>
<View style={styles.cardIcon}>{put your icon here}</View>
<View style={styles.cardText}>{put your text here}</View>
</View>
...add the other 2 rows here
</View>
And styles
cardRow: {
flexDirection: "row",
flex: 1
},
cardIcon: {
flex: 1
},
cardText: {
flex: 9
}
And add your styles for icons and text.
You can change up the cardIcon and cardText flex ratio so that you get different width for your icon.
You can make a wrapper view with alignItems: 'center' to make both text and icon vertical center
<View style={styles.cardView}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<MaterialIcons name="store" size={21} color="lightgrey" />
<Text style={styles.CardTextLayout}>{item.key}</Text>
</View>
.....
</View>

React Native: Unable to render components in a row with flex box

I am using react-native-swipeout for items within a FlatList, each list item has a 'minus' and 'plus' button either side of the text (top image).
However, when adding these components as children of the Swipeout component, they are all stacking on top of each other and to the left of the row (bottom image).
Is there something I'm missing here?
<Swipeout
style={styles.swipeStyle}
{...swipeSettings}>
<View style={styles.buttonContainer}>
<MinusButton />
</View>
<View style={styles.itemStyle}>
<Text>{this.props.name}</Text>
</View>
<View style={styles.buttonContainer}>
<PlusButton />
</View>
</Swipeout>
const styles = {
swipeStyle: {
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'flex-start'
},
buttonContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 5,
},
itemStyle: {
flex: 1,
}
};
If you look at the source code, there is another inner container that wraps the children and you cannot directly set style of the inner container.
I suggest wrap your children into a <View /> like:
<Swipeout {...swipeSettings}>
<View style={styles.swipeStyle}>
<View style={styles.buttonContainer}>
<MinusButton />
</View>
<View style={styles.itemStyle}>
<Text>{this.props.name}</Text>
</View>
<View style={styles.buttonContainer}>
<PlusButton />
</View>
</View>
</Swipeout>

Space between components in React Native styling

I have 6 View components (shown in the picture) , I want to have space between all 6 View components.
My code:
<View style={{flexDirection:'column',flex:6}}>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between'}}>
<View style={{backgroundColor:'red',flex:1}}>
</View>
<View style={{backgroundColor:'blue',flex:1}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between'}}>
<View style={{backgroundColor:'white',flex:1}}>
</View>
<View style={{backgroundColor:'black',flex:1}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between'}}>
<View style={{backgroundColor:'gray',flex:1}}>
</View>
<View style={{backgroundColor:'yellow',flex:1}}>
</View>
</View>
</View>
Try to add padding to the element then and another blank view in each row, padding make space between each item
<View style={{
flexDirection:'column',
flex:1,
}}>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between',padding:10}}>
<View style={{backgroundColor:'red',flex:2,padding:10}}>
</View>
<View style={{flex:0.1}}/>
<View style={{backgroundColor:'blue',flex:2,padding:10}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between',padding:10}}>
<View style={{backgroundColor:'white',flex:2,padding:10}}>
</View>
<View style={{flex:0.1}}/>
<View style={{backgroundColor:'black',flex:2,padding:10}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between',padding:10}}>
<View style={{backgroundColor:'gray',flex:1,padding:10}}>
</View>
<View style={{flex:0.1}}/>
<View style={{backgroundColor:'yellow',flex:1,padding:10}}>
</View>
</View>
You can simply add margins to the elements and it will work fine.
<View style={{flexDirection:'column',flex:6}}>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between', marginBottom: 10}}>
<View style={{backgroundColor:'red',flex:1, marginRight: 5}}>
</View>
<View style={{backgroundColor:'blue',flex:1, marginLeft: 5}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between', marginBottom: 10}}>
<View style={{backgroundColor:'white',flex:1, marginRight: 5}}>
</View>
<View style={{backgroundColor:'black',flex:1, marginLeft: 5}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between', marginBottom: 10}}>
<View style={{backgroundColor:'gray',flex:1, marginRight: 5}}>
</View>
<View style={{backgroundColor:'yellow',flex:1, marginLeft: 5}}>
</View>
</View>
</View>
As of React Native 0.71.0, you can use the gap property. These child views will have a gap of 10 pixels between each row / column.
<View style={{flexDirection:'column', gap: 10 }}>
<View />
<View />
<View />
<View />
<View />
<View />
</View>
If you are using the map function to render your components, you can try the following code:
// Change to the number of columns in your grid
const numCols = 4;
// Change to the spacing for each item
const spacing = '1.25rem';
// Parent View
<View style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
}}
>
{// List of child views to render
contents.map((content, index) => (
// add a margin of 'spacing' to the bottom of all cards
// will supply a left-margin to all cards in between the gap,
// everytime a card is NOT divisible numCols, add a margin to the left
<View style={{
marginBottom : spacing,
marginLeft: index % numCols !== 0 ? spacing : 0
}}
>
<Card
key={index}
content={content}
/>
</View>
))
}
</View>
I found that using the following code snippet will create an effect similar to gap in css grids.
Give the following styling to the parent container (Block/View).
justifyContent: 'space-around'
OR
justifyContent: 'space-between'
Space-around will put space between all the elements/view/items and also add space to the borders. Same as all elements get the margin.
And the space-between will put the space between all items, without adding space to the borders
All this stuff is explained here beautifully. Here is the link
Try this
const Component = () => {
return (
<View style={styles.container}>
<View style={styles.child}></View>
<View style={styles.child}></View>
</View>
);
};
// Gap you want to achieve
const gap = 8;
const styles = StyleSheet.create({
container: {
flexDirection: "row",
paddingHorizontal: (gap / -2),
},
child: {
marginHorizontal: gap / 2,
},
});
For me, the solution, among using justify-content: 'space-between', was to explicitly give width to the parent view (in my case, width: '100%'), otherwise, 'space-between' didn't do anything.
you have 2 solutions in this case
first, use margin/padding for make air between flex element
and the other way is set justifyContent to 'space-between' || 'space-around'
but you must know about some information to use the best solution in a different case
1- (margin-padding)
in some case (more case), padding better margin
as you know, if we have a box ( means element ), you have two space,
first between content and border [ Inner space ]
second, space between the border and another foreign box element [ outer space ]
if you have an element and you want move element in your style you must use margin, because if you use padding for your element, inner space changed and in many cases, this approach creates some crash in your element,
{{ if you want to use padding you must create one View and wrap all of your element and set the padding for a wrapper for you }}
and if you want to use space-between || space-around, you must know this,
space-between and space-around have one diff
in space-between, space produced between elements and not create space between your element with sides
and space-around set space with elements and with sides
You can give the parent a negative margin in the same direction you use on the children.
const Comp: FC = () => {
return (
<View style={styles.container}>
<View style={styles.item}></View>
<View style={styles.item}></View>
<View style={styles.item}></View>
<View style={styles.item}></View>
</View>
)
}
const styles = StyleSheet.create({
item: {
// Just for visual representation:
borderWidth: 2,
borderColor: '#FF0000',
height: 100,
// Important styles:
marginRight: 15,
flexBasis: '40%',
flexGrow: 1,
},
container: {
// Important styles:
marginRight: -15,
flexDirection: 'row',
flexWrap: 'wrap',
},
});
export default Comp;
<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{Array(30)
.fill({ name: "product name" })
.map((item, key, arr) => (
<View
key={key}
style={{
height: 200,
paddingTop: 15,
backgroundColor: "skyblue",
...(key % 2 !== 0
? { paddingRight: 15, paddingLeft: 15 }
: { paddingLeft: 15 }),
flexBasis: "50%",
}}
>
<View
style={{
flex: 1,
backgroundColor: variables?.BackgroundLight,
}}
>
<Text style={styles && { ...styles?.text }}>{item.name}</Text>
</View>
</View>
))}
</View>
Try this out. You can better control it using array map
If you want to put some vertical space, without flex, this is simple (just for temporary use)
<View style={{flex:2,flexDirection:"row",flexWrap: 'wrap'}}>
<View style={{backgroundColor:'white',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
<View style={{backgroundColor:'black',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",flexWrap: 'wrap'}}>
<View style={{backgroundColor:'gray',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
<View style={{backgroundColor:'yellow',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
</View>
You can add the following in your style:
attachcontainer{
flexDirection: 'row',
justifyContent: 'space-between'
}

Resources