Как обновить отдельный элемент в FlatList - React Native - PullRequest
0 голосов
/ 29 января 2020

В моем случае я пишу приложение, похожее на клон Facebook, но гораздо проще. Я помещаю каждый элемент в FlatList и отображаю их.

Чтобы «лайкнуть» пост, я нажимаю кнопку «лайк» на посте, и кнопка «лайк» становится желтой, а количество лайков увеличивается на 1 (также Я вызываю функцию addLike API после нажатия), я нажимаю ее снова, она становится серой, и количество лайков уменьшается на единицу (также я вызываю функцию удаления removeLike API).

Это то, что у меня есть: я сохраняю все загруженные посты с помощью redux - this.props, у каждого поста есть свойство «Мне нравится», которое имеет логическое значение, указывающее, понравился ли этот пост пользователю или нет, когда пользователь нажимает «Мне нравится». Теперь я делаю, когда пользователю нравится пост. вызовите действие addLike () и извлеките все сообщения для повторной подачи. Я хочу сделать это без необходимости извлекать данные снова и снова

Компонент 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);
    }
  };

Ответы [ 2 ]

1 голос
/ 29 января 2020

Предполагая, что items доступны как реквизиты . Вы можете обрабатывать изменение данных в редукторе вместо компонента React. первое, что вам нужно сделать, это

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

внутри вашего кода избыточности запустить функцию, которая обрабатывает логи c.

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 должен вызываться внутри заявление переключателя редуктора, которое соответствует вашему конкретному действию. вот так

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

Таким образом, вам не нужно извлекать данные о товарах снова и снова. Но убедитесь, что вы отправляете данные на сервер, говоря, что пост понравился или не понравился.

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});
} 
0 голосов
/ 29 января 2020

Прежде всего, спасибо @ TRome sh за его ответ.

Исходя из этого, я легко нашел решение этой проблемы

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 -> Это часть, которую я редактировал сверху ответ

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

Приветствия!

...