How to make specific component functional in a flatlist? - react-native

I am making an app where anyone can join a fantasy golf tournament. On my homepage there is a flatlist which is receiving data from api. There will be many tournaments but the user can only join the upcoming one. Now what i want to do is disable the functionality of every other tournament that means there is a join button through which user can join so i want to disable every other button and only enable the upcoming tournament button. What should i do?
here's my code
const Item = ({ title, location, date, Id }) => (
<View style={styles.renderItemView}>
<View style={styles.imageView}>
<Image style={styles.imageView2} source={require('../../assets/golf.png')} />
</View>
<View style={styles.TextView}>
<Text style={styles.Text}>Name: {title}</Text>
<Text style={styles.Text}>Location: {location}</Text>
<Text style={styles.Text}>StartDate: {moment(date).format('DD-MM-YYYY')}</Text>
<Text style={styles.Text}>Contest Fee: $49</Text>
</View>
<View style={styles.JoinView}>
<TouchableOpacity onPress={() =>{
navigation.navigate('Join', {key:Id, date});
}} style={styles.Touch1}>
<Text style={styles.JoinText}>Join</Text>
</TouchableOpacity>
</View>
</View>
);
const renderItem = ({ item }) => (
<View>
<Item title={item.name} location={item.location} date={item.startDate} Id={item.Id} />
</View>
);```

You could use row index and modulus operator to define the disabled prop like this:
const renderItem = ({ item, index }) => (
<View>
<Item title={item.name} disabled={index % 1 === 1} location={item.location} date={item.startDate} Id={item.Id} />
</View>
);`
And the use it in the Item component on the TouchableOpacity like this:
const Item = ({ disabled }) => (
<View>
...other stuff
<TouchableOpacity disabled={disabled} />
</View>
)
<TouchableOpacity disabled={props.disabled} />

Related

How to show an icon on last index of flat list

I'm trying to wrap my flat list and trying to show an Icon after last index of Flatlist. I had tried but it works fine on a single row. when we data goes to next row it would not work.
Here is my flat list code. Modal and Input both are my custom component.
const renderItem = ({item}) => {
return (
<TouchableOpacity style={[styles.tagPostContainer, styles.viewTagContainer]}>
<AppText
type={'input'}
label={`#${item}`}
color={colors.placeholder}
containerStyle={[styles.tagPostInactiveTxt, styles.BgAddedTag]}
/>
</TouchableOpacity>
);
};
return(
<>
<View style={{flexDirection:'row',justifyContent:'flex-start'}}>
<FlatList
data={tags}
renderItem={renderItem}
keyExtractor={keyExtractor}
contentContainerStyle={styles.TagFlatlist}
/>
<TouchableOpacity
style={styles.plusIconContainer}
onPress={() => setVisible(true)}>
<CreateBuildIconFocus height={13} width={13} />
</TouchableOpacity>
</View>
<Modal
visible={visible}
buttonLabel={'Done'}
containerWidth={width / 1.7}
onCancel={onCancel}
onSubmit={onClick}
containerHeight={Platform.OS === 'android' ? 200 : 200}>
<Input
placeholder={'Add Tags'}
autoFocus={true}
minWidth={120}
maxWidth={150}
value={tag}
onChangeText={text => setTag(text)}
/>
</Modal>
</>
)
FlatList styles:
TagFlatlist: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
},
Here is my design screen.
I find a solution for this. You can implement ListFooterComponent that used for showing something on end of flatlist. Here you can see more details of ListFooterComponent.
Here are the code of Flatlist.
return(
<FlatList
data={tags}
renderItem={renderItem}
keyExtractor={keyExtractor}
ListFooterComponent={
<TouchableOpacity
style={styles.plusIconContainer}
onPress={() => setVisible(true)}>
<CreateBuildIconFocus height={13} width={13} />
</TouchableOpacity>
}
contentContainerStyle={styles.TagFlatlist}
/>
)

React Native Collapse list with button

I'm making an app with expo react native, and I made a collapse that shows profile information about all users on my SQLite database.
I added a button (touchableopacity) inside the collapse and my idea is to edit information in the input where I'm showing information, but i don't know how to link the button press to the profile where is being touched.
so my code is as follows (i deleted styles to make it cleaner to see):
render(){
const miLista = this.state.datos.map((item) => //this is "list" and it works(show information of each profile and shows the button of each profile when i open the collapse of each on of them)
<ScrollView style={styles.container}>
<Collapse>
<CollapseHeader>
<Text>{item.id} {item.nombre}</Text> //here shows id and name (from sqlite data)
</CollapseHeader>
<CollapseBody >
<View key={item.id} >
<Text >Nombre</Text>
<TextInput
value={item.nombre}
onChangeText={(val) => this.setState({ nombre: val})}/>
<Text style=>Rut</Text>
<TextInput
value={item.rutPersona}
onChangeText={(val) => this.setState({ rutPersona: val})}/>
<Text >Clave</Text>
<TextInput
value={item.clave}
onChangeText={(val) => this.setState({ clave: val})}/>
{this.boton(item.id)}
</View>
</CollapseBody>
</Collapse>
</ScrollView>
);
return(
<View >
<SafeAreaView >
<TouchableOpacity
onPress={() => this.props.navigation.openDrawer()}>
<FontAwesome5 name="bars" size={24} color="#161924"/>
</TouchableOpacity>
</SafeAreaView>
<Text>Perfiles</Text>
<ScrollView>
{miLista}
</ScrollView>
</View>
);
};
so i needed to add .bind to the onpress of my button and pass the data: like this
boton(id,nombre,rutPersona,clave){
return(
<TouchableOpacity
key={id}
style={styles.boton}
onPress={this.funcionBoton.bind(this,nombre,rutPersona,clave,id)}
>
<Text>SAVE </Text>
</TouchableOpacity>
);
};

Problem with updating state in react native component

I have an array with values i want to present and then if the user press the edit button the presentation is changed to a list of TextInput components. When done editing the user can press Save or Cancel. If Cancel is pressed the values in the textInput fields should not be saved to the original array of values.
My problem is that even when pressing Cancel the data in the original array seems to be updated.
This is the code:
`
const handlePress = (text, index) => {
const newSchedule = [...scheduleTempState]
newSchedule[index].value = text
setScheduleTempState(newSchedule)
}
const handlePress2 =()=>{
setScheduleTempState([]);
console.log("handlepress2")
setEdit(false)
}
const handlePress3 =()=>{
setScheduleTempState(scheduleState);
console.log("handlepress3")
setEdit(true)
}
return (
edit
?
<View style={styles.scheduleRow}>
<View style={styles.buttonView}>
<TouchableOpacity onPress = { ()=>{saveSchedule(projectId,scheduleState);updateClient() ;setEdit(false)}} >
<MaterialIcons name="save" size={16} color="green" />
</TouchableOpacity>
<TouchableOpacity onPress = { ()=>{handlePress2()}} >
<MaterialIcons name="cancel" size={16} color="red" />
</TouchableOpacity>
</View>
<View>
<FlatList
horizontal = {true}
data={scheduleTempState}
keyExtractor={item => item.id}
renderItem={({item, index}) => {
return (
<View style={styles.decimalInputView}>
<TextInput
style={styles.cellInput}
onChangeText={(text) => {handlePress(text, index)}}
value = {item.value} />
</View>
)
}}
/>
</View>
</View>
:
<View style={styles.scheduleRow}>
<View style={styles.buttonView}>
<TouchableOpacity onPress = { ()=>handlePress3()} >
<MaterialIcons name="edit" size={14} color="black" />
</TouchableOpacity>
</View>
<View >
<FlatList
horizontal={true}
data={scheduleState}
renderItem={renderScheduleItem}
keyExtractor={item => item.id}
/>
</View>
</View>
);
}`
I guess my problem has something to do with states not being updated, but i can not see how the edited values can be saved when i press cancel.
Problem:
You are updating the scheduleTempState by referencing your scheduleState. So when you mutate scheduleTempState, it also mutates the scheduleState.
Solution: Please use spread operator to scheduleState which can help to create a new copy of a reference.
const handlePress3 =()=>{
setScheduleTempState([...scheduleState]);
...
}
Suggestion: It would be better to use explanatory names for function. It will make the code more readable. For example:
onChangeText() instead of handlepress()
onCancelEditing() instead of handlepress2()
onEdit instead of handlepress3()
Hope you will get the idea.

React Native Elements Handle ListItem click

I use React Native Elements library to create list items inside of a Flat List. I show a list of users and i need to handle style after a click.
My code is :
<View style={{flex: 1}}>
<FlatList
data={this.state.data}
renderItem={({item}) => (
<ListItem
leftAvatar={{source: {uri: item.avatar}}}
title={`${item.firstName} ${item.lastName}`}
// subtitle={item.email}
chevron
onPress={this.onItemClickHandler}
/>
)}
keyExtractor={item => item.email}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
<Button
title='Suivant'
onPress={() => navigation.navigate('LastStepToShare')}
containerStyle={{marginBottom: 15}}
/>
</View>
How can i edit the background of a clicked ListItem item ?
You could do something like this:
<FlatList
data={this.state.data}
renderItem={({item, index}) => {
const {selectedIndex} = this.state;
const itemStyle = selectedIndex === index ? styles.selected : styles.notSelected;
return (
<ListItem
leftAvatar={{source: {uri: item.avatar}}}
title={`${item.firstName} ${item.lastName}`}
style={itemStyle}
// subtitle={item.email}
chevron
onPress={() => this.onItemClickHandler(index)}
/>
)
}}
keyExtractor={item => item.email}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
and in your onItemClickHandler function, set the selectedIndex value in the state using this.setState.
Basically, get the selected index thanks to the onPress event and compare it to the current index from the renderItem function. Based on that, you can set a style variable.
Here is a sample code snippet, this might help you :
<FlatList
data={this.getAllTask()}
renderItem={({ item, index }) =>
<TouchableHighlight
onPress={() => {this.props.navigation.navigate('OtherPage', {text: item.task_name, index: index})}}>
<View style={styles.customRowContainer}>
<View style={styles.listContainer}>
<Image source={require('../Img/ic_task_icon.png')} style={styles.photo} />
<View style={styles.container_text}>
<Text style={styles.title}>
{item.task_name}
</Text>
<Text style={styles.description}>
ETA : {item.task_eta}
</Text>
</View>
</View>
</View>
</TouchableHighlight>}
keyExtractor={item => item.id}
/>
If you need to change the background color only while the item is pressed (ie. change back when the finger is up), you can customise underlayColor and activeOpacity of the underlying TouchableHighlight to achieve what you need:
<ListItem underlayColor="#ff0000" activeOpacity={1} title="Title" onPress={yourClickHandler} />
You can easily store the state of active Item, and set state on onItemClickHandler function, now you can change style according to state of item (is it active or not)
<View style={{ flex: 1 }}>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem
style={this.state.active === item.id ? styles.active : null} //***
leftAvatar={{ source: { uri: item.avatar } }}
title={`${item.firstName} ${item.lastName}`}
// subtitle={item.email}
chevron
onPress={() => this.onItemClickHandler(item.id)}
/>
)}
keyExtractor={item => item.email}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
<Button
title='Suivant'
onPress={() => navigation.navigate('LastStepToShare')}
containerStyle={{ marginBottom: 15 }}
/>
</View>
and
this.onItemClickHandler(id) => {
this.setState({
active: id
})
}

How to wrap entire section list in a TouchableOpacity component in react native

I currently have a section list in one of my components. This is the code:
<SectionList
renderItem={({item, index, section}) =>
<TouchableOpacity onPress={ () => this.onPressOrder(item) }>
<View>
<Text key={index}>
{item}
</Text>
</View>
</TouchableOpacity>
}
renderSectionHeader={({section: {title}}) => (
<Text style={{fontWeight: 'bold'}}>{title}</Text>
)}
sections={this.state.dataSource}
keyExtractor={(item, index) => item + index}
/>
the data is being pulled from this.state.dataSource
dataSource.push({
data: [
listItem.inspector,
listItem.inspection_date,
listItem.inspection_time_display,
listItem.id
],
key: keyId,
title: listItem.address
})
That's how I create my data source. Once it renders it displays like so:
The way the list renders each one of the elements on it's own line has it's own separate TouchableOpacity. What I want is for the whole block of the data to be it's own opacity. Is this possible with the SectionList data to be wrapped in a TouchableOpacity?
I don't believe it's possible to wrap each section of the section list, but it seems like you could just as easily render the entire listItem as a single item, so each section has only a single element in data.
<SectionList
renderItem={({item, index, section}) =>
// render the entire item in the `renderItem` call with one `TouchableOpacity`
<TouchableOpacity onPress={ () => this.onPressOrder(item.id) }>
<View>
<Text>
{item.inspector}
</Text>
</View>
<View>
<Text>
{item.inspection_date}
</Text>
</View>
... etc.
</TouchableOpacity>
}
renderSectionHeader={({section: {title}}) => (
<Text style={{fontWeight: 'bold'}}>{title}</Text>
)}
sections={this.state.dataSource}
keyExtractor={item => item.id}
/>
dataSource.push({
// each section just has one list item that is the full list item
data: [
listItem,
],
key: keyId,
title: listItem.address
})