Возникли проблемы при загрузке предыдущих сообщений в приложении React-native GiftedChat Chat с Firebase - PullRequest
0 голосов
/ 28 декабря 2018

Я работал над приложением чата с использованием Gifted-Chat и базы данных Firebase RealTime (и запускал его вместе с Expo).На данный момент основной обмен сообщениями работает, но я пытаюсь включить приложение для загрузки более ранних сообщений, когда пользователь прокручивает вверх и нажимает кнопку, которая появляется (мне известна опора GiftedChat для этого).К сожалению, у меня возникли проблемы с этим, и я немного озадачен.

Есть две отдельные проблемы, с которыми я столкнулся, о которых мне известно.

  1. Нажатие на loadEarlierкнопка дает мне undefined is not a function (near '...this.setState...' ошибку во время выполнения (очевидно, что-то не так с функцией скелета, которую я там поместил).
  2. Большие проблемы в том, что я до сих пор не понимаю, как загрузить n количество сообщений до самых старых загруженных в данный момент сообщений.Я посмотрел на пример GiftedChat и этот пост за помощью, но должен признаться, что я все еще потерян (лучшее, что я могу понять, это то, что мне нужно отсортировать сообщения, возможно, поотметка времени, каким-то образом получить правильный диапазон, затем проанализировать их и добавить их в массив сообщений в состоянии, но я не могу понять, как это сделать, особенно в последующих частях).

Соответствующие частиниже приведен код моего экрана чата, а также снимок экрана со структурой базы данных Firebase.Буду признателен за любую помощь по обоим этим вопросам.

// Your run of the mill React-Native imports.
import React, { Component } from 'react';
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native';
import * as firebase from 'firebase';
// Our custom components.
import { Input } from '../components/Input';
import { Button } from '../components/Button';
import { BotButton } from '../components/BotButton';
// Array of potential bot responses. Might be a fancy schmancy Markov
// chain like thing in the future.
import {botResponses} from '../Constants.js';
// Gifted-chat import. The library takes care of fun stuff like
// rendering message bubbles and having a message composer.
import { GiftedChat } from 'react-native-gifted-chat';
// To keep keyboard from covering up text input.
import { KeyboardAvoidingView } from 'react-native';
// Because keyboard avoiding behavior is platform specific.
import {Platform} from 'react-native';

console.disableYellowBox = true;

class Chat extends Component {
    state = {
        messages: [],
        isLoadingEarlier: false,
    };

    // Reference to where in Firebase DB messages will be stored.
    get ref() {
        return firebase.database().ref('messages');
    }

    onLoadEarlier() {
        this.setState((previousState) => {
          return {
            isLoadingEarlier: true,
          };
        });
        console.log(this.state.isLoadingEarlier)
        this.setState((previousState) => {
            return {
                isLoadingEarlier: false,
            };
        });
    }

    // Get last 20 messages, any incoming messages, and send them to parse.
    on = callback =>
        this.ref
          .limitToLast(20)
          .on('child_added', snapshot => callback(this.parse(snapshot)));
    parse = snapshot => {
        // Return whatever is associated with snapshot.
        const { timestamp: numberStamp, text, user } = snapshot.val();
        const { key: _id } = snapshot;
        // Convert timestamp to JS date object.
        const timestamp = new Date(numberStamp);
        // Create object for Gifted Chat. id is unique.
        const message = {
            _id,
            timestamp,
            text,
            user,
        };
        return message;
    };
    // To unsubscribe from database
    off() {
        this.ref.off();
    }

    // Helper function to get user UID.
    get uid() {
        return (firebase.auth().currentUser || {}).uid;
    }
    // Get timestamp for saving messages.
    get timestamp() {
        return firebase.database.ServerValue.TIMESTAMP;
    }

    // Helper function that takes array of messages and prepares all of
    // them to be sent.
    send = messages => {
        for (let i = 0; i < messages.length; i++) {
            const { text, user } = messages[i];
            const message = {
                text,
                user,
                timestamp: this.timestamp,
            };
            this.append(message);
        }
    };

    // Save message objects. Actually sends them to server.
    append = message => this.ref.push(message);

    // When we open the chat, start looking for messages.
    componentDidMount() {
        this.on(message =>
          this.setState(previousState => ({
              messages: GiftedChat.append(previousState.messages, message),
          }))
        );
    }
    get user() {
        // Return name and UID for GiftedChat to parse
        return {
            name: this.props.navigation.state.params.name,
            _id: this.uid,
        };
    }
    // Unsubscribe when we close the chat screen.
    componentWillUnmount() {
        this.off();
    }

    render() {
        return (
        <View>
            <GiftedChat
                loadEarlier={true}
                onLoadEarlier={this.onLoadEarlier}
                isLoadingEarlier={this.state.isLoadingEarlier}
                messages={this.state.messages}
                onSend={this.send}
                user={this.user}
            />
         </View>
        );
    }

}
export default Chat;

Screenshot of DB

Ответы [ 3 ]

0 голосов
/ 10 марта 2019

Для загрузки последних сообщений из firebase, я рекомендую использовать функцию limitToLast по вашей ссылке.После этого вы должны упорядочить результаты по дате, прежде чем позвонить и добавить в одаренный чат.

0 голосов
/ 05 мая 2019

По второму вопросу, этот вопрос должен быть таким же. Как Firebase включен и когда-то отличается?

Вы можете использовать функцию фильтра в Firebase, например, используя поле createAt для сравнения сПоследнее загруженное сообщение для загрузки больше.

0 голосов
/ 28 декабря 2018

Для вашей первой проблемы вы должны объявить вашу onLoadEarlier с функцией =>, чтобы получить текущий экземпляр this, т.е. ваш код должен выглядеть следующим образом:

onLoadEarlier = () => {
    this.setState((previousState) => {
      return {
        isLoadingEarlier: true,
      };
    }, () => {
       console.log(this.state.isLoadingEarlier)
       this.setState((previousState) => {
          return {
             isLoadingEarlier: false,
          };
       });
    }); 
}

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

Наконец, если вы используете classсинтаксис, то вы должны объявить состояние в constructor, как показано ниже:

class Chat extends Component {
   constructor (props) {
      super (props);
      state = {
         messages: [],
         isLoadingEarlier: false,
      };
   }
  ......

    onLoadEarlier = () => {
      this.setState((previousState) => {
        return {
          isLoadingEarlier: true,
        };
      }, () => {
         console.log(this.state.isLoadingEarlier)
         this.setState((previousState) => {
            return {
               isLoadingEarlier: false,
            };
         });
      }); 
  }
  ...
}

Для вашего второго ответа я обновлю ответ через некоторое время, чтобы помочь с этим.

Надеюсь, это поможет.Удачного кодирования:)

...