In my case I am writing a Facebook clone like application, but much simpler. I put each item in FlatList and render them.
To “like” a post, I press the “like” button on the post and the “like” button turns yellow and the likes count increase by 1 ( Also I call addLike API Function after clicking ), I press it again, it turns gray and likes count decrease by one ( Also I Call removeLike API Funtion ).
This is what I have so far: I store all the loaded posts with redux – this.props, each post has a property called “liked”, which is boolean, indicating whether this user has liked this post or not, when user presses “like”, Now I doing when user like the post I call the addLike() action and fetch all the posts to feed again. I want to do this without fetching data again and again
FlatList Component
<FlatList
style={styles.postList}
data={this.props.postData}
extraData={this.props}
maxToRenderPerBatch={10}
keyExtractor={item => {
return item.id;
}}
ItemSeparatorComponent={() => {
return <View style={styles.separator} />;
}}
renderItem={post => {
const item = post.item;
this.state.userisLiked = item.likedUsers.find(
user => user.id == this.state.userDetails.id,
);
// console.log('Returning Is Liked ', isLiked);
return (
<View style={styles.card}>
<View>
{item.postImage ? (
<TouchableOpacity
onPress={() =>
this.showSelectedImageFullView(item.postImage)
}>
<ImageBackground
style={styles.cardImage}
source={{
uri: Strings.AWSS3_POST_IMAGE + item.postImage,
}}>
<View style={styles.overlay} />
</ImageBackground>
</TouchableOpacity>
) : (
<View></View>
)}
</View>
<View style={{flexDirection: 'row'}}>
<Image
source={
item.user.profilePicture
? {
uri:
Strings.AWSS3_USER_PROFILE_AVATAR +
item.user.profilePicture,
}
: Images.IMAGE_PLACEHOLDER
}
style={styles.postUserImage}
/>
<View style={{flexDirection: 'column'}}>
<Text style={styles.postUserName}>
{item.user.firstName} {item.user.lastName}
</Text>
<TimeAgo
style={styles.postedTime}
time={item.createdAt}
interval={20000}
/>
</View>
<TouchableOpacity
style={styles.postMoreInfoIcon}
onPress={() => this.toggleModal(item)}>
<Image
source={Images.POST_MORE_INFO}
style={styles.postMoreInfoIcon}
/>
</TouchableOpacity>
</View>
<TouchableOpacity onPress={() => this.homeMoreInfoScreen(item)}>
<View style={{flexDirection: 'column'}}>
<Text style={styles.postTitle}>{item.title}</Text>
<Text style={styles.postBody} numberOfLines={2}>
{item.description}
</Text>
</View>
</TouchableOpacity>
<View style={styles.cardFooter}>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={() => {
this.handleUserLikes(item);
}}>
{this.state.userisLiked ? (
<Image
source={Images.POST_LIKE_CHECKED}
style={{
width: 20,
height: 20,
resizeMode: 'contain',
}}
/>
) : (
<Image
source={Images.POST_LIKE_UNCHECKED}
style={{
width: 20,
height: 20,
resizeMode: 'contain',
}}
/>
)}
</TouchableOpacity>
<Text
selectable={true}
onPress={() => this.toggleLikeModal(item)}
style={{
fontFamily: AppStyles.primaryFont,
fontSize: 15,
color: AppStyles.colorWhite,
marginLeft: 5,
}}>
{item.likesCount} Likes
</Text>
</View>
<View style={{flexDirection: 'row', marginLeft: 20}}>
<TouchableOpacity
onPress={() => this.homeMoreInfoScreen(item)}>
<Image
source={Images.POST_COMMENT}
style={{width: 20, height: 20, resizeMode: 'contain'}}
/>
</TouchableOpacity>
<Text
selectable={true}
onPress={() => this.homeMoreInfoScreen(item)}
style={{
fontFamily: AppStyles.primaryFont,
fontSize: 15,
color: AppStyles.colorWhite,
marginLeft: 5,
}}>
{item.commentsCount} Comments
</Text>
</View>
<View
style={{
flexDirection: 'row',
marginLeft: 10,
position: 'absolute',
right: 100,
top: 20,
}}>
</View>
<View
style={{
flexDirection: 'row',
marginLeft: 10,
position: 'absolute',
right: 10,
top: 20,
}}>
<TouchableOpacity
onPress={() => this.homeMoreInfoScreen(item)}>
<Text
style={{
fontFamily: AppStyles.primaryFont,
fontSize: 15,
color: AppStyles.colorWhite,
}}>
Comment
</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}}
/>
Handle User Like Action
//Add Likes to selected post click listner
handleUserLikes = item => {
//Check user already liked the post
const isLiked = item.likedUsers.find(
user => user.id == this.state.userDetails.id,
);
if (isLiked) {
this.props.removeLikeFromPost(item.id, this.state.user_token);
this.props.fetchPostData(this.state.user_token);
} else {
this.props.addLikeToPost(
item.id,
this.state.user_token,
this.state.userDetails.id,
);
this.props.fetchPostData(this.state.user_token);
}
};
2
Answers
First of all thanks to @TRomesh for his answer.
Based on that I found a solution for this issue easily
My Button Action Call
Redux Reducer Function -> This is the part I edited from above answer
Cheers !
Assuming that the
items
are available as props. You can handle the data alteration in the reducer instead of your React component. first what you have to do isinside your redux code fire a function that handles the logic.
This method
userLike
should be called inside the reducer switch statement which corresponds to your particular action. like thisIn this manner, you don’t have to fetch the items data again and again. But make sure you send the data to the back end saying the post is liked or unliked.