我希望我的用户能够针对某个主题发表评论,并能够回复评论。
我的想法是,每个主要评论都有一个包含子评论的单位列表。首先,我从屏幕上加载所有主要评论,然后每个主要评论加载其子评论,并将它们放入其 FlatList 。每个commentItem都有一个TextInput,用于设置状态。
问题是,如果一个主题的评论超过30条,屏幕将变得非常缓慢且缓慢。同样在主注释的TextInput中键入回复非常延迟。因为必须重新渲染所有内容。.很明显.setState()引起了问题。
有人知道如何构造和加载组件而不会遇到任何性能问题吗?
MainCommentItem
class CommentItem extends Component {
constructor(props) {
super(props);
this.state = {
user_fullName: "",
user_profileImgUrl: false,
sub_comments: null
};
this.renderSubComment = this.renderSubComment.bind(this);
this.loadUserData();
this.loadSubComments();
}
loadSubComments() {
firebase
.database()
.ref("Comments")
.child(this.props.comment.taskID)
.orderByChild("parentID")
.equalTo(this.props.comment.commentID)
.on("value", snap => {
if (snap.exists()) {
var comments = [];
snap.forEach(comment => {
comments.push(comment.val());
});
this.setState({
sub_comments: comments
});
}
});
}
loadUserData() {
var commentUserRef = firebase
.database()
.ref("Users")
.child(this.props.comment.posterID);
commentUserRef.once("value", snap => {
if (snap.exists()) {
try {
this.setState({
user_profileImgUrl: { uri: snap.toJSON().profileImgUrl },
user_fullName:
snap.toJSON().firstName +
" " +
snap.toJSON().lastName.charAt(0) +
"."
});
} catch (error) {
alert(error);
}
}
});
}
sendComment() {
if (this.state.comment_desc === "") return;
var commentID = firebase
.database()
.ref("Comments")
.child(this.props.comment.taskID)
.push().key;
var new_comment = {
posterID: firebase.auth().currentUser.uid,
desc: this.state.comment_desc,
date: moment().unix(),
parentID: this.props.comment.commentID,
commentID: commentID,
taskID: this.props.comment.taskID
};
this.setState({ comment_desc: "" });
firebase
.database()
.ref("Comments")
.child(this.props.comment.taskID)
.child(commentID)
.set(new_comment);
}
renderSubComment(comment) {
return <CommentItemSub comment={comment} />;
//return <Text>asdf</Text>;
}
render() {
return (
<View style={styles.offerContainer}>
<View style={styles.offerItemHolder}>
<View row>
<View>
<Text
style={{
fontSize: 15,
fontFamily: Globals.font_primary,
color: Globals.color_primary
}}
>
{this.state.user_fullName}:{" "}
</Text>
{this.state.user_profileImgUrl ? (
<FastImage
style={{
width: 30,
height: 30,
borderRadius: 15,
alignSelf: "center",
marginTop: 5,
marginBottom: 10
}}
source={this.state.user_profileImgUrl}
/>
) : (
<View style={{ width: 60, height: 60 }} />
)}
</View>
<View spread>
<Text
style={{
fontFamily: Globals.font_primary,
marginTop: 1.5,
marginRight: 5,
width: 230
}}
>
{this.props.comment.desc}
</Text>
</View>
</View>
<View row>
<View style={{ flex: 1 }}>
<TextInput
ref={r => {
this._textInputRef = r;
}}
multiline={true}
style={{
fontFamily: Globals.font_primary,
fontSize: 15,
backgroundColor: "white",
marginBottom: 2,
marginLeft: 2,
marginTop: 2,
marginRight: 2,
borderRadius: 5,
//ios
shadowOpacity: 0.15,
shadowRadius: 6,
shadowOffset: {
height: 2,
width: 1
},
//android
elevation: 2.5
}}
placeholder=" Auf Frage antworten.."
keyboardType="default"
hideUnderline={true}
value={this.state.comment_desc}
onChangeText={desc => this.setState({ comment_desc: desc })}
/>
</View>
<TouchableOpacity onPress={() => this.sendComment()}>
<FastImage
style={{
width: 22,
height: 22,
marginLeft: 10,
marginRight: 10,
marginTop: 5
}}
source={Globals.icon_send}
/>
</TouchableOpacity>
</View>
<FlatList
initialNumToRender={5}
style={{ marginLeft: 30 }}
data={this.state.sub_comments}
keyExtractor={comment => comment.commentID}
scrollEnabled={false}
renderItem={({ item: comment }) => this.renderSubComment(comment)}
/>
</View>
</View>
);
}
}
var styles = StyleSheet.create({
offerItemHolder: {},
offerContainer: {
marginTop: 5,
marginBottom: 5,
marginLeft: 2,
marginRight: 2
}
});
module.exports = CommentItem;
SubCommentItem
class CommentItemSub extends Component {
constructor(props) {
super(props);
this.state = {
user_fullName: "",
user_profileImgUrl: false,
sub_comments: null
};
this.loadUserData();
}
loadUserData() {
var commentUserRef = firebase
.database()
.ref("Users")
.child(this.props.comment.posterID);
commentUserRef.once("value", snap => {
if (snap.exists()) {
try {
this.setState({
user_profileImgUrl: { uri: snap.toJSON().profileImgUrl },
user_fullName:
snap.toJSON().firstName +
" " +
snap.toJSON().lastName.charAt(0) +
"."
});
} catch (error) {
alert(error);
}
}
});
}
sendComment() {
if (this.state.comment_desc === "") return;
var commentID = firebase
.database()
.ref("Comments")
.child(this.props.comment.taskID)
.push().key;
var new_comment = {
posterID: firebase.auth().currentUser.uid,
desc: this.state.comment_desc,
date: moment().unix(),
parentID: this.props.comment.parentID,
commentID: commentID,
taskID: this.props.comment.taskID
};
this.setState({ comment_desc: "" });
this.state.comment_desc;
firebase
.database()
.ref("Comments")
.child(this.props.comment.taskID)
.child(commentID)
.set(new_comment);
}
render() {
return (
<View style={styles.offerContainer}>
<View style={styles.offerItemHolder}>
<View row>
<View>
<Text
style={{
fontSize: 15,
fontFamily: Globals.font_primary,
color: Globals.color_primary
}}
>
{this.state.user_fullName}:{" "}
</Text>
{this.state.user_profileImgUrl ? (
<FastImage
style={{
width: 30,
height: 30,
borderRadius: 15,
alignSelf: "center",
marginTop: 5,
marginBottom: 10
}}
source={this.state.user_profileImgUrl}
/>
) : (
<View style={{ width: 60, height: 60 }} />
)}
</View>
<View spread>
<Text
style={{
fontFamily: Globals.font_primary,
marginTop: 1.5,
marginRight: 5,
width: 230
}}
>
{this.props.comment.desc}
</Text>
</View>
</View>
<View row>
<View style={{ flex: 1 }}>
<TextInput
ref={r => {
this._textInputRef = r;
}}
multiline={true}
style={{
fontFamily: Globals.font_primary,
fontSize: 15,
backgroundColor: "white",
marginBottom: 2,
marginLeft: 2,
marginTop: 2,
marginRight: 2,
borderRadius: 5,
//ios
shadowOpacity: 0.15,
shadowRadius: 6,
shadowOffset: {
height: 2,
width: 1
},
//android
elevation: 2.5
}}
placeholder=" Auf Frage antworten.."
keyboardType="default"
hideUnderline={true}
value={this.state.comment_desc}
onChangeText={desc => this.setState({ comment_desc: desc })}
/>
</View>
<TouchableOpacity onPress={() => this.sendComment()}>
<FastImage
style={{
width: 22,
height: 22,
marginLeft: 10,
marginRight: 10,
marginTop: 5
}}
source={Globals.icon_send}
/>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
var styles = StyleSheet.create({
offerItemHolder: {},
offerContainer: {
marginTop: 5,
marginBottom: 5,
marginLeft: 2,
marginRight: 2
}
});
module.exports = CommentItemSub;