Ở phần 4, chúng ta đã cùng nhau setup Authentication cho app của của chúng ta. Trong phần 5 này, chúng ta sẽ sửa dụng tài khoản mà ta đã đăng ký trên app của mình để đăng những bài viết cũng như ảnh lên app instagram clone này, kèm theo các comment và lưu xuống database của firebase. Okie! không dài dòng nữa, chúng ta bắt đầu thôi 😁.
I. Tạo from upload ảnh và caption của bài post.
Ta sẽ tận dụng modal đã có sẵn từ modal Sign In vs Sign Up để tạo một modal upload bài post của chúng ta nhé 😁.
Trong App.js
ta tạo thêm một modal như sau:
//State
const [openModalUpload, setOpenModalUpload] = useState(false);
const [image, setImage] = useState(null);
const [progress, setProgress] = useState(0);
const [caption, setCaption] = useState("");
const handleClickAddNewPost = (childData) => {
setOpenModalUpload(childData);
};
//Modal
<Modal open={openModalUpload} onClose={() => setOpenModalUpload(false)}>
<div style={modalStyle} className={classes.paper}>
<form className="form__signup">
<img className="form__logo"
src="https://www.instagram.com/static/images/web/mobile_nav_type_logo.png/735145cfe0a4.png"
alt="Logo"
/>
<div className="form__group">
<progress value={progress} max="100" />
</div>
<div className="form__group">
<Input
className="form__field"
placeholder="Enter a caption"
type="text"
value={caption}
onChange={(e) => setCaption(e.target.value)}
/>
</div>
<div className="form__group">
<input
className="form__field"
type="file"
onChange={handleChangeFile}
/>
</div>
<Button className="btn-signup" onClick={handleUpload}>
Upload
</Button>
</form>
</div>
</Modal>
Như vậy là ta đã setup xong cho phần modal để upload bài post rồi, tiếp theo ta setup việc khi ta Sign In rồi thì mới được tạo mới bài post. Trong phần Header.jsx
ta thêm button để upload post như sau:
const transferMessageAddNewPost = () => {
setAddNew(true);
props.takeMessAddNewPost(addNew);
}
//JSX
<div className="header__login">
{props.user ? (
<>
<Button className="btn btn-upload" onClick {transferMessageAddNewPost}>
<i className='bx bx-message-square-add'></i>
</Button>
<Button onClick={transferMessageLogOut} className="btn btn-login">Log out</Button>
</>) : (
<div>
<Button onClick={transferMessageLogIn} className="btn btn-login">Sign in</Button>
<Button onClick={transferMesageSignUp} className="btn btn-sign-up">Sign up</Button>
</div>
)}
</div>
Css cho button upload:
.btn-upload:hover {
background-color: #fff !important;
}
.bx-message-square-add {
font-size: 1.45rem;
font-weight: 500;
transition: all 0.5s ease;
}
.bx-message-square-add:hover {
opacity: 0.8;
text-shadow: 2px 4px 3px rgba(0,0,0,0.3);
}
Kết quả ta sẽ có được modal như hình:
II. Lưu bài post xuống database của firebase.
Trong App.js
, ta thêm đoạn code như sau:
const handleUpload = () => {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
"state_changed",
(snapshot) => {
//progress function
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(progress);
},
(error) => {
//handle Error
alert(error.message);
},
() => {
//handle when complete
storage.ref("images").child(image.name).getDownloadURL().then(
url => {
//Save link image in db of firebase
db.collection('posts').add(
{
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
caption: caption,
imageUrl: url,
userName: username
}
);
setProgress(0);
setCaption('');
setImage(null);
}
);
}
);
};
Giải thích tý về đoạn code trên:
uploadTask
: biến này để ta tham chiếu đến storage nơi lưu trữ image của chúng ta.uploadTask.on()
: Giúp ta theo giỏi quá trình upload một task lên firebase.getDownloadURL()
: Khi ta upload image lên firebase thì nó sẽ cho ta một link để sử dụng ảnh đó, dùng phương thức này để lấy link đó về và lưu vào trong docs của chúng ta.
Okie! Cùng test thử xem thế nào nhé 😁
Okie được luôn 😁
III. Thêm comment cho bài post.
Đầu tiên, UI của chúng ta đã có sẵn chỗ để ta comment luôn rồi hehe 😁. Ta tiến hành tạo collection cho các comment để test trước.
Chọn một bài post bất kỳ, sau đó click Start collection để tạo một collection comments trong bài post đó.
Bạn có thể nhập tên như hình hoặc tên nào bạn muốn cũng được, sau đó nhấn next.
Sau đó nó sẽ hiện ra bản như hình trên, theo thứ tự bạn click vào button Auto-ID để nó tự động sinh ID cho chúng ta, phần thứ 2 các bạn có thể nhập theo mình hoặc nhập sao thì tùy ý các bạn 😁, sau đó nhấn Save.
Trong file App.js
ta thêm attribute postId
và user
cho component PostItem
<PostItem key={id} postId={id} user={user} data={post} />
Trong file PostItem.jsx
ta thêm các dòng code sau:
import React, { useState, useEffect } from "react";
import { db } from "../../firebaseConfig";
import firebase from "firebase/compat";
//Sate
const [comments, setComments] = useState([]);
const [comment, setComment] = useState("");
useEffect(() => {
let unSubscribe;
if (props.postId) {
unSubscribe = db
.collection("posts")
.doc(props.postId)
.collection("comments")
.onSnapshot((snapshot) => {
setComments(
snapshot.docs.map((doc) => ({
id: doc.id,
cmt: doc.data(),
}))
);
});
}
return () => {
unSubscribe();
};
}, [props.postId]);
{/* list comment */}
<div className="post__comment--list">
{comments.map(({ id, cmt }) => (
<p key={id} className="post__comment--item">
<b>{cmt.userName}</b> {cmt.comment}
</p>
))}
</div>
{/* input field for comment */}
<div className="post__comment">
<form>
<span>
<i className="bx bx-smile"></i>
</span>
<input
value={comment}
type="text"
placeholder="Thêm bình luận..."
onChange={(e) => setComment(e.target.value)}
/>
<button
type="submit"
disabled={!comment}
className="btn btn-post-comment"
>
Đăng
</button>
</form>
</div>
Một ít css cho list comment:
/* comment list */
.post__comment--list {
padding: 0 16px;
}
.post__comment--list b {
color: rgba(38, 38, 38, 0.85);
}
.post__comment--item {
margin-bottom: 10px;
}
Okie, work ngon lành luôn 😁, tiếp theo chúng ta sẽ chức năng thêm các comment vào vài đăng lên bài post.
Trong PostItem.jsx
ta, phần button đăng các comment ta thêm hàm onClick()
như sau:
const submitComment = (e) => {
e.preventDefault();
db.collection("posts").doc(props.postId).collection("comments").add({
comment: comment,
userName: props.user.displayName,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
setComment("");
};
<button
type="submit"
disabled={!comment}
className="btn btn-post-comment"
onClick={submitComment}
>
Đăng
</button>
Xong, ta test thử xem thế nào nhé 😁.
Như vậy là chúng ta đã hoàn thành xong app instagram clone của chúng ta rồi 😁
IV. Tổng kết.
Như vậy sau 5 phần của series clone instagram với ReactJs và firebase, chúng ta đã hoàn thành xong app instagram clone đơn giản dành cho những bạn mới bắt đầu và làm quen với ReactJs, bonus thêm một ít kiến thức về firebase. Hy vọng qua series này sẽ giúp cho các bạn nắm được những căn bản về ReactJs.
Hẹn gặp lại các bạn trong những series về chủ để ReactJs tiếp theo nhé 🤗. See u again.
TỪ QUỐC HƯNG
Đam mêm lập trình Frontend, Yêu thích việc setup workspace theo phong cách tối giản
follow me :
Bài viết liên quan
NodeJS là gì? Tại sao NodeJS lại phổ biến
Jul 09, 2024 • 8 min read
Event Loop là gì? Cơ chế hoạt động của Event Loop trong JavaScript
Jun 18, 2024 • 7 min read
So sánh Golang và NodeJS chi tiết
Oct 14, 2023 • 22 min read
Home Feed UI Instagram with TailwindCSS: Giới thiệu về series
Nov 28, 2022 • 2 min read
ReactJS Tutorial for Beginners Phần 2
Dec 12, 2021 • 3 min read
ReactJS vs React Native - Gà cùng một mẹ liệu có giống nhau?
Dec 12, 2021 • 14 min read