I'm making SNS app with React Native & Firebase.
Finally, I can create a Post Title & Post Description and show it as a Flatlist.
But I don't know how to remove each post.
i already made TouchableOpacity for removing data inside Flatlist. but i don't know how i make it as a remove button.............
Please let me know where to check the document or link.
Or give me a hint. (In fact, it's been stuck here for almost two weeks.)
-----action/post
export const updateTitle = (text) => {
return { type: "UPDATE_TITLE", payload: text };
};
export const updateDescription = (text) => {
return { type: "UPDATE_DESCRIPTION", payload: text };
};
export const uploadPost = () => {
return async (dispatch, getState) => {
try {
const { post, user } = getState();
const upload = {
postTitle: post.title || " ",
postDescription: post.description || " ",
uid: user.uid,
photo: user.photo || " ",
username: user.username,
likes: [],
comments: [],
date: new Date().getTime(),
};
const ref = await db.collection("posts").doc();
upload.id = ref.id;
ref.set(upload);
} catch (e) {
alert(e);
}
};
};
export const getPosts = () => {
return async (dispatch, getState) => {
try {
const posts = await db.collection("posts").onSnapshot(function (posts) {
let array = [];
posts.forEach((post) => {
array.push(post.data());
});
dispatch({
type: "GET_POSTS",
payload: orderBy(array, "date", "desc"),
});
});
} catch (e) {
alert(e);
}
};
};
----reducers/index
const post = (state = null, action) => {
switch (action.type) {
case "UPDATE_TITLE":
return { ...state, title: action.payload };
case "UPDATE_DESCRIPTION":
return { ...state, description: action.payload };
case "GET_POSTS":
return { ...state, feed: action.payload };
case "GET_COMMENTS":
return { ...state, comments: action.payload };
default:
return state;
}
};
----screen/home
import React from "react";
import { Ionicons, SimpleLineIcons } from "@expo/vector-icons";
import {
Text,
View,
TouchableOpacity,
FlatList,
StatusBar,
} from "react-native";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { getPosts, likePost, unlikePost } from "../actions/post";
import styles from "../styles";
import moment from "moment";
import "moment/locale/ko";
moment.locale("ko");
class Home extends React.Component {
componentDidMount() {
this.props.getPosts();
}
likePost = (post) => {
const { uid } = this.props.user;
if (post.likes.includes(uid)) {
this.props.unlikePost(post);
} else {
this.props.likePost(post);
}
};
render() {
if (this.props.post === null) return null;
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<View style={styles.topTitle}>
<Text style={styles.topTitleText}>We are Vendor</Text>
</View>
<FlatList
onRefresh={() => this.props.getPosts()}
refreshing={false}
data={this.props.post.feed}
keyExtractor={(item) => item.id}
renderItem={({ item }) => {
const liked = item.likes.includes(this.props.user.uid);
return (
<View>
<View style={styles.height}>
<View
style={[
styles.row,
styles.space,
styles.marginTop,
styles.marginHorizontal,
]}
>
<Text style={[styles.bold, styles.size23, styles.grayDark]}>
{item.postTitle}
</Text>
</View>
<View
style={[styles.row, styles.space, styles.marginHorizontal]}
>
<Text
style={[
styles.bold,
styles.grayDark,
styles.marginTop7,
styles.size15,
]}
>
{" "}
{item.username}
</Text>
<Text style={[styles.gray, styles.small]}>
{moment(item.date).format("ll")}{" "}
{moment(item.date).fromNow()}
</Text>
</View>
<View
style={[
styles.marginTop,
styles.marginHorizontal,
styles.container,
]}
>
<Text
style={styles.grayDark}
ellipsizeMode={"middle"}
numberOfLines={11}
>
{item.postDescription}
</Text>
</View>
</View>
<View
style={[styles.row, styles.marginHorizontal, styles.space]}
>
<View style={[styles.row]}>
<TouchableOpacity
onPress={() => this.likePost(item)}
style={[styles.marginRight]}
>
<Ionicons
style={{ margin: 5 }}
color="#db565b"
name={liked ? "ios-heart" : "ios-heart-empty"}
size={25}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() =>
this.props.navigation.navigate("Comment", item)
}
>
<SimpleLineIcons
style={{ margin: 5 }}
color={"#3478f6"}
name="bubble"
size={22}
/>
</TouchableOpacity>
</View>
{this.props.user.uid == item.uid && (
<TouchableOpacity>
<Text>THIS IS REMOVE BUTTON</Text>
</TouchableOpacity>
)}
</View>
<View style={[styles.center, styles.border90]} />
</View>
);
}}
/>
</View>
);
}
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({ getPosts, likePost, unlikePost }, dispatch);
};
const mapStateToProps = (state) => {
return {
post: state.post,
user: state.user,
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
I would like get advise about removing comments
----action/post
export const getComments = (post) => {
return (dispatch) => {
dispatch({
type: "GET_COMMENTS",
payload: orderBy(post.comments, "date", "desc"),
});
};
};
export const addComment = (text, post) => {
return (dispatch, getState) => {
const { uid, photo, username } = getState().user;
let comments = cloneDeep(getState().post.comments.reverse());
try {
const comment = {
comment: text,
commenterId: uid,
commenterPhoto: photo || "",
commenterName: username,
date: new Date().getTime(),
postTitle: post.postTitle,
postDescription: post.postDescription,
postUser: post.username,
};
console.log(comment);
db.collection("posts")
.doc(post.id)
.update({
comments: firebase.firestore.FieldValue.arrayUnion(comment),
});
comment.postId = post.id;
comment.postTitle = post.postTitle;
comment.postDescription = post.postDescription;
comment.postUser = post.username;
comment.uid = post.uid;
comment.type = "COMMENT";
comments.push(comment);
dispatch({ type: "GET_COMMENTS", payload: comments.reverse() });
db.collection("activity").doc().set(comment);
} catch (e) {
console.error(e);
}
};
};
----comment screen
import React from "react";
import styles from "../styles";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import {
Text,
View,
TextInput,
FlatList,
KeyboardAvoidingView,
TouchableOpacity,
StatusBar,
Animated,
Dimensions,
} from "react-native";
import { addComment, getComments } from "../actions/post";
import moment from "moment";
import "moment/locale/ko";
moment.locale("ko");
import { Swipeable } from "react-native-gesture-handler";
class Comment extends React.Component {
state = {
comment: "",
};
componentDidMount = () => {
const { params } = this.props.route;
this.props.getComments(params);
};
postComment = () => {
const { params } = this.props.route;
this.props.addComment(this.state.comment, params);
this.setState({ comment: "" });
};
rightActions = (dragX) => {
const scale = dragX.interpolate({
inputRange: [-100, 0],
outputRange: [1, 0.9],
extrapolate: "clamp",
});
const opacity = dragX.interpolate({
inputRange: [-100, -20, 0],
outputRange: [1, 0.9, 0],
extrapolate: "clamp",
});
const deleteItem = async (id) => {
await db.collection("posts").doc(id).delete();
console.log("Deleted ", id);
};
return (
<TouchableOpacity>
<Animated.View style={[styles.deleteButton, { opacity: opacity }]}>
<Animated.Text
style={{
color: "white",
fontWeight: "800",
transform: [{ scale }],
}}
onPress={() => deleteItem(item.id)}
>
DELETE COMMENT
</Animated.Text>
</Animated.View>
</TouchableOpacity>
);
};
render() {
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<KeyboardAvoidingView
enabled
behavior="padding"
style={[styles.container, styles.marginTop]}
>
<FlatList
keyExtractor={(item) => JSON.stringify(item.date)}
data={this.props.post.comments}
renderItem={({ item }) => (
<View>
<Swipeable
renderRightActions={(_, dragX) => this.rightActions(dragX)}
>
<View style={[styles.row, styles.space]}>
<View style={{ margin: 10 }}></View>
<View style={[styles.container, styles.left]}>
<Text style={styles.marginTop}>
<Text style={[styles.bold, styles.grayDark]}>
{item.commenterName}
</Text>
<Text style={styles.gray}>님이 댓글을 달았습니다.</Text>
</Text>
<Text style={[styles.gray, styles.marginTop5]}>
{item.comment}
</Text>
<Text
style={[styles.gray, styles.small, styles.marginTop]}
>
{moment(item.date).format("ll")}{" "}
{moment(item.date).fromNow()}
</Text>
</View>
</View>
</Swipeable>
</View>
)}
/>
<TextInput
style={styles.input}
onChangeText={(comment) => this.setState({ comment })}
value={this.state.comment}
returnKeyType="send"
placeholder="댓글을 남겨주세요."
onSubmitEditing={this.postComment}
/>
</KeyboardAvoidingView>
</View>
);
}
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({ addComment, getComments }, dispatch);
};
const mapStateToProps = (state) => {
return {
user: state.user,
post: state.post,
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Comment);
`