(React Native) Change color to a text after onPress() it - react-native

I have a drawer with some text elements created dynamically.
I would like to select an item from the drawer, "show selected item" (like change the color of the text of that item) and re-change it to default when another one item is selected.
The text that I'd like to "change onPress" is inside the <TouchableWithoutFeedback> tag (i'm rendering some HTML code with react-native-render-html)
<FlatList
ItemSeparatorComponent={this.FlatListItemSeparator}
data={this.state.data}
renderItem={({ item }) => (
//on touch --> open article (call _onTextPress)
<TouchableWithoutFeedback onPress={this.navigateToScreen('Category', {id: item.id, title: item.name})}>
<View style={styles.categories}>
<HTML html={'<p style="color:#fd3a18; font-size:20px;"><strong>'+item.name+'</strong></p>\n'}/>
</View>
</TouchableWithoutFeedback>
)}
keyExtractor={({ id }, index) => id.toString()}
/>
navigateToScreen(routeName, params) {
return () => {
this.props.navigation.dispatch(NavigationActions.navigate({ routeName, params }))
this.props.navigation.closeDrawer();
};
}

If I understood correctly you want to change the color of selected item
//Add Selected Item to the State
state = {selectedItemId:'myId'}
// Change The State Whenever Selected
navigateToScreen(routeName, params) {
this.setState({selectedItemId:params.id})
return () => {
this.props.navigation.dispatch(NavigationActions.navigate({ routeName, params }))
this.props.navigation.closeDrawer();
};
}
Now Change the color conditionally.
<FlatList
ItemSeparatorComponent={this.FlatListItemSeparator}
data={this.state.data}
renderItem={({ item }) => (
//on touch --> open article (call _onTextPress)
<TouchableWithoutFeedback onPress={this.navigateToScreen('Category', {id: item.id, title: item.name})}>
<View style={styles.categories}>
<HTML html={`<p style="color:${this.state.selectedItemId == item.id ? "red" : "#fd3a18"}; font-size:20px;"><strong>'+item.name+'</strong></p>\n`}/>
</View>
</TouchableWithoutFeedback>
)}
keyExtractor={({ id }, index) => id.toString()}
/>

Related

Double tap on a Flatlist React Native

I'm trying to recreate Instagram's double tap on an item and a heart appears for a few seconds. Im currently rendering text items in a flatist (1 item per page) and I want the user to be able to double tap the text section and a heart will appear.
I can't seem to get both the flatList and the animation to work together. Any ideas? In my current code it will only render the flatList and not the Animated.image. I tried wrapping the animated image in an oppress in a touchable without feedback, still no luck
const onDoubleTap = useCallback(() => {
//console.log("tapped");
scale.value = withSpring(1, undefined, (isFinished) => {
if (isFinished) {
scale.value = withDelay(500, withSpring(0));
console.log("Double Tapped");
}
});
}, []);
return (
<TapGestureHandler
numberOfTaps={2}
onActivated={onDoubleTap}
>
<Animated.View>
<FlatList
horizontal={false}
decelerationRate={"fast"}
snapToAlignment={"center"}
snapToInterval={Dimensions.get("screen").height}
data={flatl}
// keyExtractor={(item, index) => `id_${index}`}
style={styles.fullScreen}
renderItem={({ item }) => (
<View style={[{ ...styles.fullHeight }]}>
<Text>{item.name}</Text>
</View>
)}
/>
<AnimatedImage
source={require("../assets/heart.png")}
style={[
styles.image,
rStyle,
]}
resizeMode={"center"}
/>
</Animated.View>
</TapGestureHandler>
);
}

Is there a way to get the Title of the selected item from another component in React Native

I have two different components "HomePage" & "ListItemCA"
In HomePage, I have a FlatList and a modal popup
<FlatList
data={ listData}
keyExtractor={list => list.Title}
renderItem={({ item }) => <ListItemCA data={item} onLongPress={openModal} />}
/>
and each list item is called from another component ListItemCA
function ListItemCA({data, onLongPress}) {
return (
<TouchableOpacity onLongPress={onLongPress} >
<View style={styles.container}>
<Text style={styles.title}>{data.Title}</Text>
<View style={styles.metaContainer}>
<Text style={styles.meta}>{( data.totalMonths != null ? data.totalMonths : '0' )} Months</Text>
<Text style={styles.meta}>{( data.members != null ? data.members.length : '0' )} Members</Text>
</View>
</View>
</TouchableOpacity>
);
}
What I want to acheive?
I want to get the selected list item title on my HomePage component. When a user longpress on a list item that title should be displayed on a modal popup. How do I pass the selected list item title to the HomePage component using longpress?
If your goal is to display data from the long pressed item in the modal, you could add the data as a parameter of your openModal function:
function openModal(data) {
// your function
return (
<Text>{data.Title}</Text>
)
}
Then, in your FlatList, modify the props of ListItemCA to call openModal for the selected item:
renderItem={({ item }) => <ListItemCA data={item} onLongPress={openModal(item)} />}
If you also want to save the data from the long pressed item in your HomePage component for other uses, you could save it in the state. In your HomePage component:
import React, { useState } from 'react'
function HomePage() {
const [itemData, setItemData] = useState()
// your code
}
Then, in your flatlist:
<FlatList
data={listData}
keyExtractor={list => list.Title}
renderItem={({ item }) =>
<ListItemCA
data={item}
onLongPress={ () => {
setItemData(item)
openModal(item)
}}
/>
}
/>
You can achieve this by passing(return) parameter from your component like this -
function ListItemCA({data, onLongPress}) {
return (
<TouchableOpacity onLongPress={() => {
onLongPress(data.Title);
//return data.Title when onLongPressed clicked
}}>
<View style={styles.container}>
...
</View>
</TouchableOpacity>
);
}
then get it in props -
<FlatList
data={listData}
keyExtractor={list => list.Title}
renderItem={({ item }) =>
<ListItemCA
data={item}
onLongPress={(title) => {//this **title** return from **onLongPress(data.Title)**
openModal();
setTitle(title);// or directly can pass that title in openModal func.
}}
/>
}
/>

How can I change the numColumns of Flatlist when changing the orientation

I created the function name getOrientation() and put it at useEffect so that whenever I rotate the device, it will rerender the component and show me which orientation the device is.
I also created the variable to determine the orientation by using hook
getOrientation()
const [orientation, setOrientation] = useState("")
const window = useWindowDimensions()
const getOrientation = () => {
if (window.height < window.width) {
setOrientation("LANDSCAPE")
} else {
setOrientation("PORTRAIT")
}
return orientation
}
at useEffect
useEffect(() => {
getOrientation()
})
console.log(orientation)
My problem is that I want to set the numsColumns = 2 in Flatlist (LANDSCAPE) and equals to 1 for the portrait mode but the error popup telling me that I cannot change the numColumns on the fly. What should I do ?
Here is my flatlist
<View style={styles.container}>
<FlatList
contentContainerStyle={{
paddingLeft: insets.left,
paddingRight: insets.right,
}}
data={dishes.dishes}
numColumns={orientation == "LANDSCAPE" ? 2 : 1}
renderItem={({ item, index }) => (
<Tile
style={styles.tileItem}
key={index}
title={item.name}
caption={item.description}
onPress={() => navigation.navigate('Dishdetail_Screen', { dishId: item.id })} // passing infor from one to another screen
// chevron={false}
featured
imageSrc={{
uri: baseUrl + item.image
}}
/>
)}
keyExtractor={item => item.id.toString()} />
</View>
This creepy error
enter image description here
P/s: I'm the fresh React-Native developer. Thanks everyone who is checking my problems
Try adding a key prop to your Flatlist like so with the value being ur orientation:
<FlatList
key={orientation} // add key prop here
contentContainerStyle={{
paddingLeft: insets.left,
paddingRight: insets.right,
}}
data={dishes.dishes}
numColumns={orientation == "LANDSCAPE" ? 2 : 1}
renderItem={({ item, index }) => (
<Tile
style={styles.tileItem}
key={index}
title={item.name}
caption={item.description}
onPress={() => navigation.navigate('Dishdetail_Screen', { dishId: item.id })} // passing infor from one to another screen
// chevron={false}
featured
imageSrc={{
uri: baseUrl + item.image
}}
/>
)}
keyExtractor={item => item.id.toString()} />

How to control swapping on click of button in carousel in react-native?

When I will click on button I want to control my swapping slides of carousel .That means if I will click on button then new slide will come in carousel.
I am using 'react-native-snap-carousel' package for achieve my functionality in react-native.so please help me how I can achieve this functionality.Thank you in advance.
SwapSlide = (value) => {
this.setState({ indexvalue: value }, () => {
console.log("get swapindex ===>>>", this.state.indexvalue)
})
}
onPressAnswer = (item) => {
console.log("run increase method===>>>", this.increase('progress', 10));
console.log("run swapslide method===>>>", this.SwapSlide.snapToNext());
this.AddQuestionAnswer(item)
}
renderItemAnswer = ({ item, index }) => {
return (
<View>
<TouchableOpacity style={styles.answerTouchable} onPress={() =>this.onPressAnswer(item)}>
<Text style={styles.answerText}>{item.answer}</Text>
</TouchableOpacity>
</View>
)
}
<Carousel
data={questionList}
renderItem={this.renderItemQuestion}
hasParallaxImages={true}
itemWidth={wp('100%')}
sliderWidth={wp('100%')}
ref={(value)=>{this.SwapSlide=value}}
/>
<TouchableOpacity onPress={() => { this.setState({ indexvalue: indexvalue + 1 }) }}><Text style={styles.skiptext}>Skip</Text></TouchableOpacity>
Use method snapToNext() for next slide
<TouchableOpacity onPress={() => this.SwapSlide.snapToNext()}><Text style={styles.skiptext}>Skip</Text></TouchableOpacity>
For Previous slide you can use this.SwapSlide.snapToPrev()

FlatList not rendering style dynamically

I'm currently struggling in making my FlatList applying the changes I do to it. What I am wanting right now is that when I click an item in my flatlist, that it highlights in a certain color. I followed an approach done by a guy but I am having the problem that to me is not working the update once I click.
I can see through console that all I am doing performs a modification but I think that I am missing some point with extraData parameter since it is not re-rendering with the backgroundColor that I would like to apply.
The code I have is as following, I know that the style I am applying is correct since if i substitute in the map styles.list per styles.selected, everything gets the background I would like to be applied to the elements I click.
So summarizing, the issue I think I have is that the flatlist is not re-rendering so it doesn't show the modifications I perform on it. Any idea of what I am doing wrong? Any tip?
render() {
const { students, studentsDataSource, loading, userProfile } = this.props.navigation.state.params.store;
this.state.dataSource = studentsDataSource._dataBlob.s1.map(item => {
item.isSelect = false;
item.selectedClass = styles.list;
return item;
})
const itemNumber = this.state.dataSource.filter(item => item.isSelect).length;
return (
<View style={styles.container}>
<Item rounded style={styles.searchBar}>
<Input placeholder='Group Name'/>
</Item>
<FlatList
style={{
flex: 1,
width: "100%",
}}
data={this.state.dataSource}
ItemSeparatorComponent={this.FlatListItemSeparator}
renderItem={ ({ item }) => (
<ListItem avatar style={[styles.list, item.selectedClass]}
onPress={() => this.selectItem(item)}>
<Left>
{!item.voteCount && <Avatar unseen={true} /> }
{!!item.voteCount > 0 && <Avatar />}
</Left>
<Body>
<Text>{item.name}</Text>
<Text note>{item.group}</Text>
</Body>
</ListItem>
)
}
listKey={item => item.key}
extraData={this.state}
/>
</View>
);
}
Here we can find the state and SelectItem functions:
constructor(props) {
super(props)
this.state = {
dataSource : [],
}
}
//FlatListItemSeparator = () => <View style={styles.line} />;
selectItem = data => {
//{console.log("inside SelectItem=", data)}
data.isSelect = !data.isSelect;
data.selectedClass = data.isSelect? styles.selected: styles.list;
const index = this.state.dataSource.findIndex( item => data.key === item.key);
this.state.dataSource[index] = data;
this.setState({
dataSource: this.state.dataSource,
});
console.log("This state has the changes:=",this.state.dataSource)
};
Well the main issue was that I was not using the .setState and instead I was doing assignations which killed the listeners.