React Native: как обрабатывать состояние для каждого элемента в визуализированном FlatList при нажатии кнопки «Мне нравится»? - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь обработать состояние значка «сердце» в визуализированном плоском списке (который загружает данные из Firebase) для каждого отдельного элемента в плоском списке.

Код работает, в этом значок сердца заполняется, и данные передаются в базу данных при нажатии значка. Аналогичным образом, повторное нажатие на значок сердца возвращает значок и удаляет «лайк» из базы данных.

Однако при нажатии на значок сердца происходит переключение между заполненным состоянием и пустым состоянием для значка сердца для каждый элемент в списке, когда я пытаюсь изменить состояние для этого определенного c элемента.

Я понимаю, что мне нужно обрабатывать состояние локально для каждого элемента в плоском списке, но я не знаю, как это сделать. Любая помощь будет оценена. Код ниже:

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

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Хорошо, так что проблема в том, что у вас есть единственное значение состояния liked вместо массива. Сначала вы должны изменить liked на массив (в котором будут храниться идентификаторы понравившихся сообщений). Может быть, назвать это чем-то более подходящим, например likePosts. Затем вы можете добавлять или удалять идентификаторы записей из массива, когда они нравятся или не нравятся (и проверять значение в массиве likedPosts при определении того, какой значок отображать).

Ваш измененный код должен выглядеть примерно так это:

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

, поскольку this.state.liked будет иметь значение true для всех элементов в респоне json, чтобы исправить его, вы можете обновить массив состояний json

 ItemPRessed =(index)=>{let dataArray = this.state.data
  dataArray[index].liked = !dataArray[index].liked
  this.setState({
    data:dataArray
  })}

и вместо this.state.liked использовать post.liked, поэтому он будет задан c для элемента, и вместо this.setState({liked: true}); put

this.ItemPRessed(Index)

я не знаю, как ваши индексы работают в вашем json put, если это так

[{item},{item}]

, затем вы можете использовать renderItem=({item: post, index}) вместо renderItem={({item: post})

, чтобы получить индекс, по которому элемент нажимается, затем

...