简体   繁体   English

如何更新 FlatList 中的单个项目 - React Native

[英]How to update a single item in FlatList - React Native

In my case I am writing a Facebook clone like application, but much simpler.就我而言,我正在编写一个类似 Facebook 的克隆应用程序,但要简单得多。 I put each item in FlatList and render them.我将每个项目放在 FlatList 中并呈现它们。

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 ).要“喜欢”帖子,我按帖子上的“喜欢”按钮,“喜欢”按钮变为黄色,喜欢计数增加 1(单击后我也调用 addLike API 函数),我再次按下它,它会转动灰色和喜欢计数减一(我也调用 removeLike API 函数)。

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.这就是我到目前为止所拥有的:我使用 redux - this.props 存储所有加载的帖子,每个帖子都有一个名为“喜欢”的属性,它是布尔值,指示该用户是否喜欢该帖子,当用户按下“喜欢”,现在当用户喜欢帖子时,我会调用 addLike() 操作并获取所有帖子以再次供稿。 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);
    }
  };

Assuming that the items are available as props .假设这些items可以作为props 使用 You can handle the data alteration in the reducer instead of your React component.您可以在 reducer 中而不是在 React 组件中处理数据更改。 first what you have to do is首先你要做的是

  handleUserLikes = item => {
    this.props.addLikeToPost({
        item_id:item.id,
        user_token:this.state.user_token,
        user_id:this.state.userDetails.id,
      });
  };

inside your redux code fire a function that handles the logic.在您的 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}
}

This method userLike should be called inside the reducer switch statement which corresponds to your particular action.这个方法userLike应该在对应于您的特定操作的 reducer switch 语句中调用。 like this像这样

function appReducer(state = initialState, action) {
  switch (action.type) {
   .........
   case 'YOU_ACTION' :
    return  userLike(state,action);
   }
}

In 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.但请确保您将数据发送到后端,说明该帖子是喜欢的还是不喜欢的。

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});
} 

First of all thanks to @TRomesh for his answer.首先感谢@TRomesh的回答。

Based on that I found a solution for this issue easily基于此,我很容易找到了解决此问题的方法

My Button Action Call我的按钮操作调用

 handleUserLikes = item => {
    this.props.addLikeToPost({
        item_id:item.id,
        user_token:this.state.user_token,
        user_id:this.state.userDetails.id,
      });
  };

Redux Reducer Function -> This is the part I edited from above answer Redux Reducer Function ->这是我从上面的答案中编辑的部分

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};
};

Cheers !干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM