Unable to align the content to the top of the screen - react-native

I'm writing a react native code where I'm trying to split the screen into 2. There are 3 tabs, and based on the tab I click, I need to display the content. Here My issue is, the content is getting displayed. But the content displayed is not from the top of the screen.
Here is my code.
import { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
const App = () => {
const [facetGroup, setFacetGroup] = useState([
{ name: 'tab 1', index: 1, description: 'tab one description' },
{ name: 'tab 2', index: 2, description: 'tab two description' },
{ name: 'tab 3', index: 3, description: 'tab three description' },
]);
const [selectedIndex, setSelectedIndex] = useState(1);
const handlePress = (index) => {
setSelectedIndex(index);
};
return (
<View style={styles.mainContainer}>
<View style={{ flexDirection: 'col' }}>
{facetGroup.map((item: any) => (
<View key={item.index} style={styles.menuContainer}>
<TouchableOpacity
onPress={() => handlePress(item.index)}
style={styles.title}>
<Text>{item.name}</Text>
</TouchableOpacity>
</View>
))}
</View>
<View>
{facetGroup.map((item: any) => (
<View key={item.index} style={styles.descContainer}>
<View style={{ marginLeft: 40 }}>
{selectedIndex === item.index && <Text>{item.description}</Text>}
</View>
</View>
))}
</View>
</View>
);
};
export default App;
const styles = StyleSheet.create({
mainContainer: { flex: 1, height: 500, flexDirection: 'row' },
menuContainer: {
backgroundColor: '#fff',
textAlign: 'center',
height: 40,
border: '1px solid black',
padding: 20,
},
descContainer: {
backgroundColor: '#fff',
height: 400,
marginTop: 0,
justifyContent: 'flex-start',
},
});
And here is working fiddle. Please let me know how can I fix this.
Thanks

Related

React Native: How do I switch the state of only one item in FlatList?

what happens is the following fact: I want to add "switch/toggle" next to id 2.3 and 4 items, but it's getting on all items on the flatlist. I used "import SwitchSelector from "react-native-switch-selector"; " Can anyone who understands flatlist help me? I will be very happy and grateful
I'm not getting it at all, and I'm thinking of redoing my code because of this problem
Settings.js
import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image} from 'react-native';
import SwitchSelector from "react-native-switch-selector";
import React, {useState} from 'react'
const Settings = () => {
const [data, setdata] = useState(DATA);
const [isRender, setisRender] = useState(false);
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png')},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png')},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png')},
{id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png')},
//{id: 5, text: 'Logout'},
]
const renderItem = ({item}) => {
return(
<TouchableOpacity style= {styles.item}>
<View style={ styles.avatarContainer }>
<Image source={ item.image } style={ styles.avatar } />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
//marginHorizontal: 21
},
item:{
borderBottomWidth: 1,
borderBottomColor: '#808080',
alignItems: 'flex-start',
flexDirection: 'row',
},
avatarContainer: {
backgroundColor: 'transparent',
//borderRadius: 100,
height: 30,
width: 30,
justifyContent: 'center',
alignItems: 'center'
},
avatar: {
height: 25,
width: 25,
bottom: -25,
marginLeft: 30
},
text:{
marginVertical: 30,
fontSize: 20,
fontWeight: 'bold',
marginLeft: 30,
marginBottom: 10,
bottom: 5
}
});
export default Settings;
Well here is my approach to your problem as much as I understood;
it also actively changes the values of data for further usage of App
const [data, setData] = useState([
{ id: 1, text: 'Perfil', image: require('../../assets/images/user.png'), chosen: false },
{ id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png'), chosen: false },
{ id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png'), chosen: false },
{ id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png'), chosen: false },
//{id: 5, text: 'Logout'},
])
const [isRender, setisRender] = useState(false);
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.item}>
<View style={styles.avatarContainer}>
<Image source={item.image} style={styles.avatar} />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
{item.id > 1 && <Switch
thumbColor={item.chosen == false ? "red" : "green"}
value={item.chosen}
onChange={() => setData(data.map(index =>
item.id === index.id
? {...index, chosen : !index.chosen}
: index
))}
/>}
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={data}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);};
You could try adding a boolean property to each item in DATA. You could then conditionally show a <SwitchSelector /> in renderItem based on that property.
For example, below I added the property showSwitch and used a ternary expression to conditionally show a <SwitchSelector /> in renderItem:
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png'), showSwitch: false},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png'), showSwitch: true},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png'), showSwitch: true},
{id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png'), showSwitch: true},
//{id: 5, text: 'Logout'}
]
...
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.item}>
<View style={styles.avatarContainer}>
<Image source={item.image} style={styles.avatar} />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
{item.showSwitch ? <SwitchSelector /> : null}
</TouchableOpacity>
);
};
This works from me:
import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image, Switch} from 'react-native';
import React, {useState, useEffect} from 'react';
import {TouchID} from 'react-native-touch-id';
const Settings = () => {
const [data, setdata] = useState(DATA);
const [isRender, setisRender] = useState(false);
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png'), switch: false},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png'), switch: true},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png'), switch: true},
{id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png'), switch: true},
//{id: 5, text: 'Logout'}
]
const renderItem = ({item}) => {
return(
<TouchableOpacity
style= {styles.item}
>
<View style={ styles.avatarContainer }>
<Image source={ item.image } style={ styles.avatar } />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
{item.switch ? <Switch /> : null}
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
//marginHorizontal: 21
},
item:{
borderBottomWidth: 1,
borderBottomColor: '#808080',
alignItems: 'flex-start',
flexDirection: 'row',
},
avatarContainer: {
backgroundColor: 'transparent',
//borderRadius: 100,
height: 30,
width: 30,
justifyContent: 'center',
alignItems: 'center',
},
avatar: {
height: 25,
width: 25,
bottom: -25,
marginLeft: 30
},
text:{
marginVertical: 30,
fontSize: 20,
fontWeight: 'bold',
marginLeft: 30,
marginBottom: 10,
bottom: 5
},
});
export default Settings;

React Native Images FlatList Error "doesn't show the images"

enter image description here
I relied on this video, here's the github with the video code:
https://github.com/KasperKloster/ComponentsExplained/blob/main/App.js
https://www.youtube.com/watch?v=qGN3S0wO-OQ
i'm not getting to view the icon images in png and neither in svg, could they help me? I put a bacgroundColor in some random color just to see if the icons are there, and they are, only they are not showing up.. i also couldn't put logout at the bottom of the screen
Settings.js
import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image} from 'react-native';
import React, {useState} from 'react'
const Settings = () => {
const [data, setdata] = useState(DATA);
const [isRender, setisRender] = useState(false);
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png')},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png')},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png')},
{id: 4, text: 'Logout'},
]
const renderItem = ({item}) => {
return(
<TouchableOpacity
style= {styles.item}
>
<View style={ styles.avatarContainer }>
<Image loadingIndicatorSource={ item.image } style={ styles.avatar } />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
//marginHorizontal: 21
},
item:{
borderBottomWidth: 1,
borderBottomColor: '#808080',
alignItems: 'flex-start',
flexDirection: 'row',
},
avatarContainer: {
backgroundColor: '#A0D800',
borderRadius: 100,
height: 30,
width: 30,
justifyContent: 'center',
alignItems: 'center',
},
avatar: {
height: 50,
width: 50,
},
text:{
marginVertical: 30,
fontSize: 25,
fontWeight: 'bold',
marginLeft: 30,
marginBottom: 5
},
});
export default Settings;
change loadingIndicatorSource={ item.image } to source={ item.image }

Is there a way to Button click show/hide functional component in React native

Is there a way to show and hide component on button click in react native functional component? I have a function in which two custom buttons. I want to show view if one button selected and if second button select then first button view hide and showing second button view. How can i achieve this?
Here is my function code..
const SupportScreen = ({ props, navigation }) => {
const lists = [
{id: 1, title: 'Pending Tickets'},
{id: 2, title: 'Resolved Tickets'},
];
const [selected, setSelected] = useState(1);
<View style={{flexDirection: 'row', marginTop: 10}}>
{lists.map(list => (
<CustomButton
key={list.id}
customclick={() => {
handleColor(list);
}}
title={list.title}
style={{
backgroundColor:
list.id === selected
? Constants.Colors.PRIMARY
: Constants.Colors.WALLTE_TXT_GRAY_COLOR,
width: 180,
elevation: 3,
}}
tColor={Constants.Colors.WHITE}
tfz={12}></CustomButton>
))}
</View>
const handleColor = row => {
setSelected(row.id);
};
</SafeAreaView>
);
};
You can achieve it like this
Working Example
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
const lists = [
{ id: 1, title: 'Pending Tickets' },
{ id: 2, title: 'Resolved Tickets' },
];
export default function App() {
const [selected, setSelected] = React.useState(lists[0].id);
return (
<View style={styles.container}>
{lists.map((list) => (
<Button
key={list.id}
title={list.title}
onPress={() => setSelected(list.id)} // Set Selected to this id
color={list.id === selected ? 'dodgerblue' : 'grey'} // Render depending on the id
style={{
width: 180,
elevation: 3,
}}
/>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
});
For Rendering a View based on the ID, you can do something like this
{selected == 1 ? (
<View>
<Text>View One Here</Text>
</View>
) : (
<View>
<Text>View Two Here</Text>
</View>
)}
Check out my sample
import * as React from 'react';
import { Text, View, StyleSheet, Pressable } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
const lists = [
{ id: 1, title: 'Pending Tickets 1', color: '#ff0000' },
{ id: 2, title: 'Resolved Tickets 2', color: '#ffff00' },
{ id: 3, title: 'Resolved Tickets 3', color: '#ff00ff' },
{ id: 4, title: 'Resolved Tickets 4', color: '#00ffff' },
{ id: 5, title: 'Resolved Tickets 5', color: '#ccccc' },
{ id: 6, title: 'Resolved Tickets 6', color: '#00ff00' },
];
const [selected, setSelected] = React.useState(1);
const handleColor = () => {
setSelected((selected % lists.length) + 1);
};
return (
<View style={styles.container}>
<View style={{ flexDirection: 'row', marginTop: 10 }}>
{lists
.filter((item, index) => index === selected - 1)
.map((list, index) => {
return (
<Pressable
onPress={() => {
handleColor();
}}>
<Text style={{color: list.color}}>{list.title}</Text>
</Pressable>
);
})
.filter(Boolean)}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

React native - Flatlist onPress is returning all the dataset not only the one selected

I am trying to use the Flatlist component to show some registers and select some multiple registers.
<FlatList
horizontal
bounces={false}
key={ingredientList.id}
data={ingredientList}
renderItem={({ item }) => (
<Card key={item.id} onPress={selectedIngredient(item)}>
<Text key={item.title} style={styles.titleText}>{item.name}</Text>
<ImageBackground key={item.illustration} source={item.illustration} style={styles.cardImage}></ImageBackground>
</Card>
)
}
keyExtractor={(item) => item.index}
/>
function selectedIngredient(item) {
console.log('selecionado: ' + item.name)
}
How can I do to get only the details about the Card I selected?
this is what the "ingredientList" return:
Array [
Object {
"id": 8,
"name": "leite condensado",
},
Object {
"id": 9,
"name": "creme de leite",
},
You can use TouchableOpacity for the click event.
Snapshot:
Here is the working example of how you can implement it:
import React, { useState } from 'react';
import {
Text,
View,
StyleSheet,
FlatList,
TouchableOpacity,
} from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
// or any pure javascript modules available in npm
const ingredientList = [
{
id: 1,
name: 'item1',
},
{
id: 2,
name: 'item 2',
},
{
id: 3,
name: 'item 3',
},
{
id: 8,
name: 'item 4',
},
{
id: 4,
name: 'item 5',
},
{
id: 5,
name: 'item 6',
},
];
export default function App() {
const [selectedItem, setSelectedItem] = useState(null);
const selectedIngredient = (item) => {
console.log('selecionado: ' + item.name);
setSelectedItem(item);
};
return (
<View style={styles.container}>
<FlatList
style={styles.flatlist}
horizontal
bounces={false}
key={ingredientList.id}
data={ingredientList}
renderItem={({ item }) => (
<TouchableOpacity
style={styles.flatListItem}
key={item.id}
onPress={() => selectedIngredient(item)}>
<Text>{item.name}</Text>
</TouchableOpacity>
)}
keyExtractor={(item) => item.index}
/>
{selectedItem ? (
<View style={styles.selectedTextView}>
<Text style={styles.selectedText}>{`${selectedItem.name} selected`}</Text>
</View>
) : (
<View style={styles.selectedTextView}>
<Text style={styles.selectedText}>{`Nothing selected`}</Text>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
flatListItem: {
width: 100,
height: 100,
backgroundColor: 'white',
margin: 5,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
},
selectedTextView: {
flex: 1,
backgroundColor: 'white',
margin: 5,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
fontSize: 20
},
selectedText: {
fontSize: 30
},
});
Working Demo: Expo Snack
Try this const selectedIngredient = (item) => { console.log(item); }
and
<Card key={item.id} onPress={() => selectedIngredient(item)}>

How to update/ refresh the expandable list view in react native

I am developing an android app using react native which includes a cart page. I have used [ExpandableListView]:https://aboutreact.com/expandable-list-view/) to show the items grouped under categories. Each Item has a '+' and '-' button to change the count. Here is my code:
DetailScreen.js:
import React, { Component } from 'react';
import { LayoutAnimation, StyleSheet, TouchableOpacity, View, Text, ScrollView, UIManager, Platform, TextInput, KeyboardAvoidingView, ImageBackground, Picker, Image, Linking, Alert, } from 'react-native';
export default class DetailsScreen extends Component
{
static navigationOptions = {
title: 'Details',
header: null,
}
constructor(props)
{
super(props);
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
this.state =
{
listDataSource: [
{
isExpanded: false,
category_name: 'Item 1',
subcategory: [{ id: 1, val: 'Sub Cat 1', count:'0' }, { id: 3, val: 'Sub Cat 3', count:'0' }],
},
{
isExpanded: false,
category_name: 'Item 2',
subcategory: [{ id: 4, val: 'Sub Cat 4', count:'0' }, { id: 5, val: 'Sub Cat 5', count:'0' }],
}],
};
}
updateLayout = index => {
LayoutAnimation.configureNext
(LayoutAnimation.Presets.easeInEaseOut);
const array = [...this.state.listDataSource];
array[index]['isExpanded'] = !array[index]['isExpanded'];
this.setState(() => {
return {
listDataSource: array,
};
});
};
updateSalonData = newData =>
{
console.log('new Data: ' + JSON.stringify(newData));
var tempData = [...this.state.listDataSource];
let index = tempData.findIndex(x => x.category_name === newData.category_name);
tempData[index] = newData;
this.setState(() => {
return {
listDataSource: tempData,
};
});
};
render() {
return (
<View style={{ marginStart: 10, marginEnd: 10, marginTop: 5, borderBottomWidth: 0.5 }}></View>
<Text style={styles.topHeading}>Services</Text>
<ScrollView enabled keyboardShouldPersistTaps={'handled'} showsVerticalScrollIndicator={false} contentContainerStyle={{ flexGrow: 1, }}>
{this.state.listDataSource.map((item, key) => (
<ExpandableItemComponent
key={item.category_name}
onClickFunction={this.updateLayout.bind(this, key)}
item={item}
updateSalonData = {this.updateSalonData.bind(this, item)}/>
))}
</ScrollView>
</View>
);
}
}
ExpandableItemComponent.js:
import React, { Component } from 'react';
import { LayoutAnimation, StyleSheet, View, Text, ScrollView, UIManager, TouchableOpacity, Platform, } from 'react-native';
export default class ExpandableItemComponent extends Component {
//Custom Component for the Expandable List
constructor(props) {
super(props);
console.log('props: ' + JSON.stringify(props.item));
this.state = {
layoutHeight: 0,
dataSource:props.item,
};
}
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps');
if (nextProps.item.isExpanded) {
this.setState(() => {
return {
layoutHeight: null,
};
});
} else {
this.setState(() => {
return {
layoutHeight: 0,
};
});
}
console.log('next Item: ' + JSON.stringify(nextProps.item) + "\n");
this.setState(() => {
return {
dataSource: nextProps.item,
};
});
}
shouldComponentUpdate(nextProps, nextState) {
if (this.state.layoutHeight !== nextState.layoutHeight) {
return true;
}
return false;
}
setItemCount = (id) =>
{
const tempItem = this.props.item;
const data = this.props.item.subcategory;
const index = data.findIndex(x => x.id === id);
// console.log('pricing Index: ' + index);
if (index !== -1) {
data[index]["cartCount"] = 10;
tempItem.subcategory = data;
this.props.updateSalonData(tempItem);
}
}
render() {
return (
<View>
{/*Header of the Expandable List Item*/}
<TouchableOpacity
activeOpacity={0.8}
onPress={this.props.onClickFunction}
style={styles.header}>
<Text style={styles.headerText}>{this.state.dataSource.category_name}</Text>
</TouchableOpacity>
<View
style={{
height: this.state.layoutHeight,
overflow: 'hidden',
}}>
{/*Content under the header of the Expandable List Item*/}
{this.state.dataSource.subcategory.map((item, key) => (
<TouchableOpacity
key={key}
style={styles.content}
onPress={() => alert('Id: ' + item.id + ' val: ' + item.val)}>
<View style={{ flex: 1, flexDirection: 'row', alignContent: 'center', justifyContent: 'space-between'}}>
<Text style={styles.text}>{item.val}</Text>
<View style={{ flexDirection: 'row', alignSelf: 'center', }}>
<Text style={styles.text}>{item.val}</Text>
<View style={{ height: 25, width: 75, flexDirection: 'row', borderRadius: 15, borderWidth: 1, alignSelf: 'center', justifyContent: 'space-evenly', borderColor: 'orange', overflow: 'hidden' }}>
<View style={{ alignContent: 'center', justifyContent: 'center' }}>
<Text onPress={()=>{this.setItemCount(item.id)}} style={{ width: 25, height: 25, fontSize: 12, color: 'orange', fontWeight: 'bold', textAlign: 'center', textAlignVertical: 'center' }}>+</Text>
</View>
<View style={{ borderWidth: 1, borderColor: 'orange', backgroundColor: 'orange', alignContent: 'center', justifyContent: 'center' }}>
<Text style={{ width: 25, height: 25, fontSize: 12, color: 'white', fontWeight: 'bold', textAlign: 'center', textAlignVertical: 'center' }}>{item.cartCount}</Text>
</View>
<View style={{ alignContent: 'center', justifyContent: 'center' }}>
<Text style={{ width: 25, height: 25, fontSize: 12, color: 'orange', fontWeight: 'bold', textAlign: 'center', textAlignVertical: 'center' }}>-</Text>
</View>
</View>
</View>
</View>
{/* <View style={styles.separator} /> */}
</TouchableOpacity>
))}
</View>
<View style={styles.separator} />
</View>
);
}
}
Now the problem is, When i click '+' button the count is actually incremented in the code but its not been updated in the UI. But when I collapse and expand the same item, now the value is updated. Someone Pls guide me to update the count once I click the + button.
Can you replace your this.state.dataSource to direct this.props.updateSalonData on ExpandableItemComponent.js
If an update was done in the parent class it will automatically update in child class if so do.
eg:
...
{this.props.updateSalonData.subcategory.map((item, key) => (
....
like this.