如何更新 FlatList 中的单个项目 - React Native
How to update a single item in FlatList - React Native
就我而言,我正在编写类似 Facebook 的克隆应用程序,但要简单得多。我把每个项目都放在 FlatList 中并渲染它们。
给"like"一个post,我按下post上的"like"按钮,"like"按钮变成黄色,点赞数增加1(我也调用了 addLike API Function after click),我再次按下它,它变成灰色并且喜欢计数减少了一个(我也调用了 removeLike API Function)。
这是我目前所拥有的:我将所有加载的 post 存储在 redux - this.props 中,每个 post 都有一个名为 [=29] 的 属性 =],这是一个布尔值,表明这个用户是否喜欢这个post,当用户按下"like",现在我在用户喜欢post时调用addLike()操作并获取所有 posts 以再次提供。我想这样做而不是一次又一次地获取数据
FlatList 组件
<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>
);
}}
/>
处理用户喜欢的操作
//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);
}
};
假设 items
可用作 props。您可以在 reducer 而不是 React 组件中处理数据更改。首先你要做的是
handleUserLikes = item => {
this.props.addLikeToPost({
item_id:item.id,
user_token:this.state.user_token,
user_id:this.state.userDetails.id,
});
};
在你的 redux 代码中触发一个处理逻辑的函数。
const userLike =(state,payload)=>{
let Newitem = null;
let item= state.item.find(
user => item.id == payload.item_id
);
let itemIndex = state.item.findIndex(
user => user.id == payload.item_id
);
let isLiked = item.likedUsers.find(user=>user.id===payload.user_id);
if(isLiked){
Newitem = {...item,likedUsers:item.likedUsers.filter(user=>user.id!==payload.user_id)}
} else{
Newitem = {...item,likedUsers:[...item.likedUsers,payload.user_id]}
}
let Newitems = [
state.items.slice(0, itemIndex),
Newitem,
state.items.slice(++itemIndex)
];
return {...state,items:Newitems}
}
此方法 userLike
应在对应于您的特定操作的 reducer switch 语句中调用。像这样
function appReducer(state = initialState, action) {
switch (action.type) {
.........
case 'YOU_ACTION' :
return userLike(state,action);
}
}
通过这种方式,您不必一次又一次地获取项目数据。但是请确保将数据发送到后端,说明 post 是喜欢还是不喜欢。
const addLikeToPost = (data) => dispatch => {
// you can send a request to your back end here without Awaiting.
// data is passed from the addLikeToPost method called from you react component.
dispatch({action:'YOU_ACTION',payload:data});
}
首先感谢@TRomesh的回答。
基于此,我轻松找到了解决此问题的方法
我的按钮操作调用
handleUserLikes = item => {
this.props.addLikeToPost({
item_id:item.id,
user_token:this.state.user_token,
user_id:this.state.userDetails.id,
});
};
Redux Reducer 函数 -> 这是我根据上面的答案编辑的部分
const userLike = (state, payload) => {
console.log('TCL: userLike -> payload', payload.payload);
console.log('TCL: userLike -> state.postData', state.postData);
let item = state.postData.find(user => user.id == payload.payload.item_id);
let local_data = state.postData;
let isLiked = item.likedUsers.find(
user => user.id === payload.payload.user_id,
);
if (isLiked) {
local_data = local_data.map(data => {
if (data.id == payload.payload.item_id) {
data.likesCount = Number(data.likesCount - 1);
}
return data;
});
} else if (isLiked == undefined || isLiked == null) {
local_data = local_data.map(data => {
if (data.id == payload.payload.item_id) {
data.likesCount = Number(data.likesCount + 1);
}
return data;
});
}
return {...state, postData: local_data};
};
干杯!
就我而言,我正在编写类似 Facebook 的克隆应用程序,但要简单得多。我把每个项目都放在 FlatList 中并渲染它们。
给"like"一个post,我按下post上的"like"按钮,"like"按钮变成黄色,点赞数增加1(我也调用了 addLike API Function after click),我再次按下它,它变成灰色并且喜欢计数减少了一个(我也调用了 removeLike API Function)。
这是我目前所拥有的:我将所有加载的 post 存储在 redux - this.props 中,每个 post 都有一个名为 [=29] 的 属性 =],这是一个布尔值,表明这个用户是否喜欢这个post,当用户按下"like",现在我在用户喜欢post时调用addLike()操作并获取所有 posts 以再次提供。我想这样做而不是一次又一次地获取数据
FlatList 组件
<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>
);
}}
/>
处理用户喜欢的操作
//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);
}
};
假设 items
可用作 props。您可以在 reducer 而不是 React 组件中处理数据更改。首先你要做的是
handleUserLikes = item => {
this.props.addLikeToPost({
item_id:item.id,
user_token:this.state.user_token,
user_id:this.state.userDetails.id,
});
};
在你的 redux 代码中触发一个处理逻辑的函数。
const userLike =(state,payload)=>{
let Newitem = null;
let item= state.item.find(
user => item.id == payload.item_id
);
let itemIndex = state.item.findIndex(
user => user.id == payload.item_id
);
let isLiked = item.likedUsers.find(user=>user.id===payload.user_id);
if(isLiked){
Newitem = {...item,likedUsers:item.likedUsers.filter(user=>user.id!==payload.user_id)}
} else{
Newitem = {...item,likedUsers:[...item.likedUsers,payload.user_id]}
}
let Newitems = [
state.items.slice(0, itemIndex),
Newitem,
state.items.slice(++itemIndex)
];
return {...state,items:Newitems}
}
此方法 userLike
应在对应于您的特定操作的 reducer switch 语句中调用。像这样
function appReducer(state = initialState, action) {
switch (action.type) {
.........
case 'YOU_ACTION' :
return userLike(state,action);
}
}
通过这种方式,您不必一次又一次地获取项目数据。但是请确保将数据发送到后端,说明 post 是喜欢还是不喜欢。
const addLikeToPost = (data) => dispatch => {
// you can send a request to your back end here without Awaiting.
// data is passed from the addLikeToPost method called from you react component.
dispatch({action:'YOU_ACTION',payload:data});
}
首先感谢@TRomesh的回答。
基于此,我轻松找到了解决此问题的方法
我的按钮操作调用
handleUserLikes = item => {
this.props.addLikeToPost({
item_id:item.id,
user_token:this.state.user_token,
user_id:this.state.userDetails.id,
});
};
Redux Reducer 函数 -> 这是我根据上面的答案编辑的部分
const userLike = (state, payload) => {
console.log('TCL: userLike -> payload', payload.payload);
console.log('TCL: userLike -> state.postData', state.postData);
let item = state.postData.find(user => user.id == payload.payload.item_id);
let local_data = state.postData;
let isLiked = item.likedUsers.find(
user => user.id === payload.payload.user_id,
);
if (isLiked) {
local_data = local_data.map(data => {
if (data.id == payload.payload.item_id) {
data.likesCount = Number(data.likesCount - 1);
}
return data;
});
} else if (isLiked == undefined || isLiked == null) {
local_data = local_data.map(data => {
if (data.id == payload.payload.item_id) {
data.likesCount = Number(data.likesCount + 1);
}
return data;
});
}
return {...state, postData: local_data};
};
干杯!