[英]React Native: how to handle state for each item in a rendered FlatList when pressing the 'like' button?
I'm trying to handle the state for a 'heart' icon in a rendered Flat List (which loads data from Firebase) for each individual item within the Flat List.我正在尝试为平面列表中的每个单独项目处理 state 在呈现的平面列表(从 Firebase 加载数据)中的“心”图标。
The code works, in that the heart icon fills in and the data is pushed to the database when the icon is pressed.该代码有效,因为填充了心形图标,并在按下图标时将数据推送到数据库。 Likewise, pressing the heart icon again reverts the icon and removes the 'like' from the database.
同样,再次按下心形图标将恢复图标并从数据库中删除“喜欢”。
However, when the heart icon is clicked, it swaps between the filled in state and hollow state for the heart icon for every item in the list, when I'm trying to alter state for that specific item.但是,当单击心形图标时,它会在填充的 state 和空心 state 之间切换,用于列表中每个项目的心形图标,当我尝试更改特定项目的 Z9ED39E2EA931586B6A985A6942EF5 时
I understand that I need to handle state locally for each item in the Flat List, but I've no idea how to do it.我知道我需要为 Flat List 中的每个项目在本地处理 state,但我不知道该怎么做。 Any help would be appreciated.
任何帮助,将不胜感激。 Code below:
下面的代码:
import React, {Component} from 'react';
import {
FlatList,
Text,
View,
} from 'react-native';
import {Icon} from 'react-native-elements';
import {globalStyles} from '../config/Styles';
import Firebase from 'firebase';
import 'firebase/database';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
//set value of postList variable as an empty array
postList: [],
liked: false,
};
}
componentDidMount() {
this.getPostData();
}
getPostData = () => {
const ref = Firebase.database().ref('/posts');
ref.on('value', snapshot => {
const postsObject = snapshot.val();
if (!postsObject) {
console.log('NO DATA IN FIREBASE:', Date(Date.now()));
} else {
console.log('HOMESCREEN FIREBASE DATA RETRIEVED:', Date(Date.now()));
const postsArray = Object.values(postsObject);
this.setState({postList: postsArray});
}
});
};
render() {
return (
<View>
<FlatList
keyExtractor={post => post.id}
data={this.state.postList}
renderItem={({item: post}) => (
<View style={globalStyles.postContainer}>
<Text style={globalStyles.postText}>
{post.heading}
{'\n'}@{' '}
<Text style={{fontWeight: 'bold'}}>{post.location}</Text>
{'\n'}
{post.description}
{'\n'}
listed by{' '}
<Text style={{fontWeight: 'bold'}}>{post.createdBy}</Text>
{'\n'}
on <Text style={{fontWeight: 'bold'}}>{post.createdAt}</Text>
</Text>
<View style={globalStyles.iconMargin}>
<Icon
raised
iconStyle={globalStyles.icon}
name={this.state.liked ? 'heart' : 'heart-o'}
size={28}
type="font-awesome"
onPress={() => {
const userKey = Firebase.auth().currentUser.uid;
const postKey = post.id;
const favRef = Firebase.database().ref(
'favourites/' + userKey + '/' + postKey,
);
if (this.state.liked === false) {
favRef.set({
id: postKey,
heading: post.heading,
description: post.description,
location: post.location,
createdAt: post.createdAt,
createdBy: post.createdBy,
});
this.setState({liked: true});
} else {
favRef.remove();
this.setState({liked: false});
}
}}
/>
<Icon
raised
iconStyle={globalStyles.icon}
name="flag-o"
size={28}
type="font-awesome"
onPress={() =>
this.props.navigation.navigate('ReportPostScreen', post)
}
/>
</View>
</View>
)}
/>
</View>
);
}
}
becuase this.state.liked will be true for all items in the json respone to correct it you can update the state array json因为 this.state.liked 将适用于 json 响应中的所有项目以更正它,您可以更新 stateFCA366 数组
ItemPRessed =(index)=>{let dataArray = this.state.data
dataArray[index].liked = !dataArray[index].liked
this.setState({
data:dataArray
})}
and instead of this.state.liked
use post.liked
so it will be specific to the item and instead of this.setState({liked: true});
而不是
this.state.liked
使用post.liked
所以它将特定于项目而不是this.setState({liked: true});
put放
this.ItemPRessed(Index)
i don't know how your indexs work in your json put if it is like this我不知道你的索引在你的 json 中是如何工作的,如果是这样的话
[{item},{item}]
then you can use renderItem=({item: post, index})
instead of renderItem={({item: post})
那么你可以使用
renderItem=({item: post, index})
而不是renderItem={({item: post})
to get the index on which item it is pressed then获取按下它的项目的索引
Ok so the issue is that you've got a singular liked
state value instead of an array.好的,问题是你有一个单一的
liked
state 值而不是数组。 You should firstly change liked
to an array (which will store the id of the posts which are liked).您应该首先将
liked
的内容更改为一个数组(它将存储被喜欢的帖子的 ID)。 Maybe call it something more appropriate such as likePosts
.也许将其称为更合适的名称,例如
likePosts
。 Then you can add or remove post ids from the array when they're liked or unliked (and check the likedPosts
array for the value when deciding what icon to display).然后,您可以在喜欢或不喜欢它们时从数组中添加或删除帖子 ID(并在决定显示什么图标时检查
likedPosts
数组的值)。
Your modified code should look something like this:您修改后的代码应如下所示:
import React, {Component} from 'react';
import {
FlatList,
Text,
View,
} from 'react-native';
import {Icon} from 'react-native-elements';
import {globalStyles} from '../config/Styles';
import Firebase from 'firebase';
import 'firebase/database';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
//set value of postList variable as an empty array
postList: [],
likedPosts: [],
};
}
componentDidMount() {
this.getPostData();
}
getPostData = () => {
const ref = Firebase.database().ref('/posts');
ref.on('value', snapshot => {
const postsObject = snapshot.val();
if (!postsObject) {
console.log('NO DATA IN FIREBASE:', Date(Date.now()));
} else {
console.log('HOMESCREEN FIREBASE DATA RETRIEVED:', Date(Date.now()));
const postsArray = Object.values(postsObject);
this.setState({postList: postsArray});
}
});
};
render() {
return (
<View>
<FlatList
keyExtractor={post => post.id}
data={this.state.postList}
renderItem={({item: post}) => (
<View style={globalStyles.postContainer}>
<Text style={globalStyles.postText}>
{post.heading}
{'\n'}@{' '}
<Text style={{fontWeight: 'bold'}}>{post.location}</Text>
{'\n'}
{post.description}
{'\n'}
listed by{' '}
<Text style={{fontWeight: 'bold'}}>{post.createdBy}</Text>
{'\n'}
on <Text style={{fontWeight: 'bold'}}>{post.createdAt}</Text>
</Text>
<View style={globalStyles.iconMargin}>
<Icon
raised
iconStyle={globalStyles.icon}
name={this.state.likedPosts.indexOf(post.id) > -1 ? 'heart' : 'heart-o'}
size={28}
type="font-awesome"
onPress={() => {
const userKey = Firebase.auth().currentUser.uid;
const postKey = post.id;
const favRef = Firebase.database().ref(
'favourites/' + userKey + '/' + postKey,
);
// This checks that the array doesn't contain the post id (i.e. the post was not previously liked)
if (this.state.likedPosts.indexOf(post.id) === -1) {
favRef.set({
id: postKey,
heading: post.heading,
description: post.description,
location: post.location,
createdAt: post.createdAt,
createdBy: post.createdBy,
});
// Include the post.id in the likedPosts array
this.setState({ likedPosts: [...this.state.likedPosts, post.id] })
} else {
favRef.remove();
// Remove the post.id from the likedPosts array
let index = this.state.likedPosts.indexOf(post.id);
this.setState({ likedPosts: this.state.likedPosts.splice(index, 1) })
}
}}
/>
<Icon
raised
iconStyle={globalStyles.icon}
name="flag-o"
size={28}
type="font-awesome"
onPress={() =>
this.props.navigation.navigate('ReportPostScreen', post)
}
/>
</View>
</View>
)}
/>
</View>
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.