Change unique item in FlatList using ExtraData - react-native

I have on flatList that renders 5 TouchableOpacity. I want to change borderColor from the one I press in my flatList without changing the other, and do it with index that saved in state
<FlatList data={this.state.data} keyExtractor={item => item.id}
numColumns={columns}
renderItem={({ item }) => {
if (item.empty) {
return <View style={[Cards.item, Cards.itemEmpty]} />;
}
return (<View style={[{ flex: 1 }]}>
<TouchableOpacity onPress={() => this.onPressChangeColor(item.id)}
style={[Cards.item, {
backgroundColor: "grey",
borderColor: "grey",
borderWidth: 2
}]}>
<Text style={[{ color: "white", textAlign: 'center', alignSelf: 'center' }]}>{item.name}</Text>
</TouchableOpacity>
</View>);
}
}
/>

You need to find the unique TouchableOpacity:
save the index in state:
state = {
index: null
}
save the unique index inonPressChangeColor function like this:
onPressChangeColor = (id,index) => {
//do what you want with the id
this.setState({index})
}
and the FlatList with some changes:
<FlatList data={this.state.data} keyExtractor={item => item.id}
numColumns={columns}
renderItem={({ item, index }) => {
if (item.empty) {
return <View style={[Cards.item, Cards.itemEmpty]} />;
}
return (<View style={[{ flex: 1 }]}>
<TouchableOpacity onPress={() => this.onPressChangeColor(item.id, index)}
style={[Cards.item, {
backgroundColor: "grey",
borderColor: index == this.state.index ? "green" : "grey",
borderWidth: 2
}]}>
<Text style={[{ color: "white", textAlign: 'center', alignSelf: 'center' }]}>{item.name}</Text>
</TouchableOpacity>
</View>);
}
}
/>

Related

How to scroll To next item on a button click using FlatList in React Native?

I have an array of months which I am using to display months using a horizontal FlatList. I want the months to change using 2 buttons that are forward button to change the month in increasing order i.e from January to February and so on and a back button to change the month backwards i.e from January to December.
How can I make the buttons do so. Below monthName is an array that contains all the month names.
<ScrollView style={{flexGrow: 1}}>
<View style={{flex: 1, backgroundColor: '#fff', height: hp('130')}}>
<View
style={{
justifyContent: 'space-evenly',
width: wp('48'),
}}>
<FlatList
data={monthName}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
renderItem={(month, index) => (
<View>
<Months
showMonth={month.item}
id={month.id}
refer={flatRef}
/>
</View>
)}
keyExtractor={(item, index) => item.id.toString()}
horizontal
// snapToInterval={Dimensions.get('window').width}
snapToAlignment={'center'}
ref={(node) => (flatRef = node)}
/>
</View>
<View
style={{
justifyContent: 'space-evenly',
width: wp('12'),
}}>
{/* {} */}
<IonIcons.Button --> the button that makes the month increment.
name="arrow-forward"
size={25}
backgroundColor="white"
color="black"
// onPress={() => console.log('pressed')}
onPress={() => {
flatRef.scrollToIndex({index: ?});
}}
/>
</View>
</View>
</ScrollView>
try to access ref using current and it should work
this.flatRef.current.scrollToIndex({index: monthName.length > this.state.currentindex ? this.state.currentindex++ : this.state.currentindex });
import React, { useRef } from 'react';
import {
FlatList,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import { wp } from '../../constants/scaling';
import { colors } from '../../constants/theme';
import bookingprocess from '../../data/BookingProcess';
import { textStyles } from '../../styles/textStyles';
import { RFValue } from 'react-native-responsive-fontsize';
import AntDesign from 'react-native-vector-icons/AntDesign';
const BookingProcess = ({}) => {
const flatListRef = useRef(FlatList);
const nextPress = index => {
if (index <= 2) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index + 1
});
}
};
const backPress = index => {
if (index >= 1) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index - 1
});
}
};
return (
<View
style={{
...styles.cardView,
padding: 0,
elevation: 0,
borderWidth: 1,
borderColor: '#f2f2f2',
overflow: 'hidden'
}}>
<View
style={{
padding: wp(2),
backgroundColor: colors.primaryColor
}}>
<Text
style={{
...textStyles.heading,
color: '#fff'
}}>
Booking Process
</Text>
</View>
<Text
style={{
...textStyles.mediumheading,
padding: wp(2),
paddingBottom: 0
}}>
You can reserve your parking slot in advance. Please follow
these four simple steps to book your parking slot.
</Text>
<FlatList
data={bookingprocess}
horizontal={true}
ref={flatListRef}
contentContainerStyle={{ padding: wp(2) }}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => item.id}
renderItem={({ item, index }) => {
return (
<View style={styles.innerCard}>
{item.image}
<View style={styles.ButtonBox}>
<TouchableOpacity
onPress={() => backPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="leftcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => nextPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="rightcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
</View>
<View style={styles.innercardHeaderView}>
<Text style={styles.headingTextNumber}>
{item.id}. {item.title}
</Text>
</View>
<Text style={styles.description}>
{item.description}
</Text>
</View>
);
}}
/>
</View>
);
};
export default BookingProcess;
const styles = StyleSheet.create({
cardView: {
backgroundColor: colors.white,
margin: wp(2),
elevation: 4,
borderRadius: wp(2),
padding: wp(2),
width: wp(94)
},
innerCard: {
margin: wp(2),
borderRadius: wp(2),
padding: wp(0),
paddingTop: 0,
paddingHorizontal: 0,
overflow: 'hidden',
width: wp(90),
elevation: 5,
marginLeft: 0,
padding: wp(2),
backgroundColor: '#fff'
},
ButtonBox: {
position: 'absolute',
flexDirection: 'row',
right: 0,
justifyContent: 'space-between',
width: wp(20),
padding: wp(2)
},
innercardHeaderView: {
backgroundColor: '#0000',
flexDirection: 'row',
padding: wp(2),
paddingBottom: 0,
alignItems: 'center'
},
headingTextNumber: {
...textStyles.heading,
color: colors.primaryColor,
textAlign: 'center',
alignSelf: 'center',
textAlignVertical: 'center'
},
description: {
...textStyles.mediumheading,
paddingHorizontal: wp(2),
textAlign: 'justify'
}
});
Instead of using a FlatList I would suggest you to make a state variable and execute it like this
Working example - Here
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { AntDesign } from '#expo/vector-icons';
...
const [SelectMonth, SetSelectMonth] = React.useState(monthName[0]);
const NextPress = () => {
if (SelectMonth.id !== 12) {
let temp = monthName.find((c) => c.id === SelectMonth.id + 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
const PrevPress = () => {
if (SelectMonth.id !== 1) {
let temp = monthName.find((c) => c.id === SelectMonth.id - 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
return (
<View style={styles.container}>
<View style={styles.CalenderBox}>
<AntDesign
name="caretleft"
size={30}
color="black"
onPress={() => PrevPress()}
/>
<View style={styles.MonthNameBox}>
<Text style={{ fontWeight: 'bold', fontSize: 24 }}>
{SelectMonth.name}
</Text>
</View>
<AntDesign
name="caretright"
size={30}
color="black"
onPress={() => NextPress()}
/>
</View>
</View>
);

can not use delete functionality in flatlist renderItem

Delete functionality is not working in flatlist renderItem method, but it will work perfectly fine if I use map function to render data instead of flatlsit.
Here is the sample code
class App extends Component {
state = {
todos: [
{ todo: 'go to gym', id: 1 },
{ todo: 'buy a mouse', id: 2 },
{ todo: 'practice hash table', id: 3 },
{ todo: 'iron clothes', id: 4 }
]
};
keyExtractor = item => item.id.toString();
handleDelete = id => {
const todos = this.state.todos.filter(item => item.id !== id);
this.setState({ todos });
};
renderItems({ item }) {
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between'
}}
>
<Text style={{ fontSize: 16 }}>{item.todo}</Text>
<TouchableOpacity
onPress={() => this.handleDelete(item.id)}
style={{ marginRight: 15 }}
>
<Text style={{ color: 'red' }}>Delete</Text>
</TouchableOpacity>
</View>
);
}
render() {
return (
<View>
{/* {this.renderItems()} */}
<FlatList
data={this.state.todos}
keyExtractor={this.keyExtractor}
renderItem={this.renderItems}
/>
</View>
);
}
}
I can't understand the reason it gives me the error _this2.handleDelete is not a function.
You were not binding your function, in your constructor bind the function or use array function
renderItems = ({ item }) => {
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<Text style={{ fontSize: 16 }}>{item.todo}</Text>
<TouchableOpacity
onPress={() => this.handleDelete(item.id)}
style={{ marginRight: 15 }}>
<Text style={{ color: 'red' }}>Delete</Text>
</TouchableOpacity>
</View>
);
}

how to Use if in FlatList

I have array which has images. I want to give show images in flatlist everything is ok now. But I want to show some of them I mean if condition is true show that image.
this is my code:
renderItem={ ({ item }) =>
{
if (true) {
<View style={{ width: '22%', marginLeft: '3%', marginTop: '2%', alignItems: 'center' }} >
<TouchableOpacity onPress={() => this.props.navigation.navigate('DescriptionPage', { data: item.call })}>
<ImageBackground source={item.img} style={{ width: 60, height: 60 }} />
</TouchableOpacity>
</View>
}
else {
...
}
}
}
if I use like this there is no error and it shows all images.
<FlatList
data={images}
keyExtractor={(item, index) => index.toString()}
numColumns={4}
renderItem={ ({ item }) =>
<View style={{ width: '22%', marginLeft: '3%', marginTop: '2%', alignItems: 'center' }} >
<TouchableOpacity onPress={() => this.props.navigation.navigate('DescriptionPage', { data: item.call })}>
<ImageBackground source={item.img} style={{ width: 60, height: 60 }} />
</TouchableOpacity>
</View>
}
/>
There is mistake here I dont know why :
{
if (true)
{
...
}
else
{
...
}
}
you forgot to add return inside if else condition:
do it like this:
renderItem={ ({ item }) =>
{
if (true) {
// add return
return(
<View style={{ width: '22%', marginLeft: '3%', marginTop: '2%', alignItems: 'center' }} >
<TouchableOpacity onPress={() => this.props.navigation.navigate('DescriptionPage', { data: item.call })}>
<ImageBackground source={item.img} style={{ width: 60, height: 60 }} />
</TouchableOpacity>
</View>
)
}
else {
// add return
return(
...
)
}
}
}
Just use this kind of setup:
return (isTrue) ?
<TouchableOpacity onPress={() => this.props.navigation.navigate('DescriptionPage', { data: item.call })}>
<ImageBackground source={item.img} style={{ width: 60, height: 60 }} />
</TouchableOpacity> : null;
This should render the component if it is true, else, it won't render anything.

Change the style of row in FlatList using SetNativeProps

<FlatList
data={this.state.bankDetail}
renderItem={({ item, index }) => this.bankImgView(item, index)}
keyExtractor={(item, index) => index}
horizontal={false}
numColumns={4}
/>
bankImgView(item, index) {
return (
<TouchableOpacity onPress={() => this.selectBank(item.image, item.text, index)}>
<View ref={"img"+index} style={{ backgroundColor: "white", marginTop: 2.5, justifyContent: "center", marginLeft: 6, alignItems: "center", flex: 1, marginBottom: 2.5 }}>
<View style={{ width: width / 4 - 8, height: 90, justifyContent: "center", alignItems: "center" }}>
<Image source={{ uri:item.image }} style={{ height: 60, width: 60 }} />
</View>
</View>
</TouchableOpacity>
)
}
selectBank(bankImage,bankName,index) {
this.refs["img"+index].setNativeProps({ backgroundColor: "red" });
}
I wanted to change the background color of a view using setNativeProps which is in flatList but it not changed , the error encounters "setNativeProps of undefined".So Please provide me the correct way for doing this.
Change selectBank function to
selectBank = (bankImage,bankName,index) => {
this.refs["img"+index].setNativeProps({ backgroundColor: "red" });
}
You are accessing references in a function where this is changed and this.refs["img"+index] is undefined.
So change it accordingly to es6 so that this is bind automatically.

implement tabs in the center of the screen

I am new to react native. i have implemented stacknavigator inside drawernavigator. Using this library
"react-navigation": "^1.0.0-beta.11",
Now i want to implement tabs within the screen at the center. Following image is part of my screen
i dont have any idea how can i do this with any library or manually putting views.
Any help is appreciated.
Thanks
Well, I've solved that scenario using react-native-swiper
Basically you have to wrap all views you want to have inside a Swiper, render and style the header as you want.
Here there is a working example I've made:
render() {
return (
<View style={styles.body}>
<Swiper
height={500}
showsPagination={true}
loop={false}
renderPagination={this._renderPagination}
ref={component => this._swiper = component}>
<View style={styles.page}>
<FlatList data={..} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
</Swiper>
</View>
);
}
_renderPagination(index, total, context) {
return (
<View style={styles.pagination}>
{this._renderPaginationHeaders(index, total, context)}
</View>
)
}
_renderPaginationHeaders(index, total, context) {
let ret = [];
for (let i = 0; i < total; i++) {
ret.push(
<TouchableOpacity key={i} style={{ flex: 1, flexDirection: 'column' }} onPress={() => this._onPageChange(i)}>
<Text style={[styles.title, { flex: 1, textAlign: 'center', textAlignVertical: 'center' }]}>
{this._getSectionText(i)}
</Text>
<View style={{ height: 5, backgroundColor: index === i ? 'magenta' : 'transparent' }}></View>
</TouchableOpacity>
);
}
return ret;
}
_onPageChange(targetIndex) {
const currentIndex = this._swiper.state.index;
const offset = targetIndex - currentIndex;
this._swiper.scrollBy(offset);
}
const styles = StyleSheet.create({
body: {
flex: 1,
alignItems: 'center',
alignSelf: 'center',
backgroundColor: '#f1f1f1',
},
pagination: {
flexDirection: 'row',
width: Dimensions.get('window').width,
height: Header.currentHeight * 0.7,
backgroundColor: '#2E2E2E',
paddingLeft: 2,
paddingRight: 2,
alignItems: 'center',
position: 'absolute',
top: 0,
},
page: {
flex: 1,
marginTop: (Header.currentHeight * 0.7) + 3
},
title: {
color: 'white'
},
});