Related
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;
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 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,
},
});
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)}>
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.