我一直在使用Gifted-Chat和Firebase RealTime数据库(并在Expo上运行它)开发一个聊天应用程序。在这一点上,基本的消息传递有效,但是当用户向上滚动并单击出现的按钮时,我试图启用应用程序以加载较早的消息(我知道为此提供了GiftedChat道具)。不幸的是,我在执行此操作时遇到了麻烦,感到有些困惑。
我已经意识到有两个独立的问题。
undefined is not a function (near '...this.setState...'
运行时错误(很明显,我放置在此处的骨架函数有问题)。下面是我的聊天屏幕的代码相关部分,以及我的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;
答案 0 :(得分:1)
对于第一个问题,应使用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,
};
});
});
}
...
}
对于第二个答案,我会在某个时候更新答案以帮助您解决。
希望这会有所帮助。快乐编码:)
答案 1 :(得分:0)
要从firebase加载最后一条消息,建议您在参考上使用limitToLast函数。之后,您应按日期顺序对结果进行排序,然后在有才华的聊天中调用追加。
答案 2 :(得分:0)
对于第二个问题,该问题应与How Firebase on and once differ?相同
您可以在Firebase中使用过滤器功能,例如,使用createdAt字段与上次加载的邮件进行比较以加载更多邮件。