Trang chủ Kiến Thức Công Nghệ Hướng dẫn clone instagram với React JS và Firebase phần 2.
Công Nghệ

Hướng dẫn clone instagram với React JS và Firebase phần 2.

Chia sẻ
Hướng dẫn clone instagram với React JS và Firebase phần 2.
Chia sẻ

Trong phần 1 của series này, chúng ta tiến hành setup một project ReactJS bằng câu lệnh create-react-app, đăng ký và tạo app trên firebase để có thể sử dụng và lưu trữ data. Trong phần 2 này, chúng ta sẽ tạo header cho nó và tạo component post để hiển thị bài đăng nhé 😉. Nào bắt đầu thôi 😁!

I. Tạo header cho app.

Đầu tiên, run project của chúng ta lên bằng câu lệnh npm start, sau đó vào App.js và xóa hết các đoạn code demo của React đi nhé, nhớ là xóa code trong thẻ <p id="app"></p>, import logo from "./logo.svg"; thôi nhé 🤣, trong App.css ta cũng xóa hết đi.

Trong folder src ta tạo một folder components đây là nơi chúng ta dùng để lưu trữ các component của chúng ta về sau, như hình dưới:

file App.js là file gốc, chứa các component cha để render ra một page hoàn chỉnh. Cấu trúc trong file App.js của chúng ta trong bài này sẽ như sau:

Trong folder components ta tạo một folder với tên là Header và trong nó tạo thêm 2 file là Header.jsxStyle-Header.css. Chúng ta sẽ code phần header và style cho nó trong hai file này, sau đó ta sẽ import nó vào trong App.js và sử dụng thôi 😁.

Trong Header.jsx ta code như sau:

JS

import React from "react";
import "./Style-Header.css";

export default function Header() {
  return (
    <p className="container">
            <p className="header">
                <p className="header__logo">
                    <img
                    src="https://www.instagram.com/static/images/web/mobile_nav_type_logo.png/735145cfe0a4.png"
                    alt="Logo"
                    />
                </p>
                <p className="header__search">
                    <input type="text" placeholder="Tìm kiếm"/>
                    <i className='bx bx-search-alt-2' ></i>
                </p>
                <p className="header__login">
                    <button className="btn btn-login">Login</button>
                </p>
            </p>
        </p>
  );
}

import component Header vào App.js như hình.

Các icon mình sử dụng thằng Boxicon, các bạn có thể vào đây để lấy link css và thêm vào file index.html ở folder public nhé 😉

Phần logo bạn có thể sử dụng luôn link ảnh của Instagram chính chủ nha 😁, nhớ phải import css của header vào trong component Header nữa nhé. Sau khi xong ta sẽ được UI cơ bản như hình.

Chúng ta sẽ style cho phần header nào 😉, trong file Style-Header.css ta thêm css cho nó như sau:

CSS

.container {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #fff;
    height: 54px;
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 3;
    border-bottom: 1px solid #dbdbdb;
}

.header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 54px;
    max-width: 975px;
    padding: 0 20px;
    width: 100%;
    z-index: 10;
}

.header__logo img {
    object-fit: contain;
}

.header__search {
    display: flex;
    align-items: center;
    height: 28px;
    flex: 0 1 auto;
    min-width: 125px;
    width: 215px;
    -webkit-box-flex: 0;
    position: relative;
}

.header__search input {
    font-size: 14px;
    border: solid 1px #dbdbdb;
    outline: none;
    padding: 3px 10px 3px 26px;
    z-index: 2;
    color: #262626;
    background-color: #fafafa;
}

.header__search i.bx-search-alt-2 {
    position: absolute;
    z-index: 15;
    padding-left: 10px;
}

.btn {
    padding: 5px 15px;
    border: 1px solid transparent;
    border-radius: 4;
    cursor: pointer;
}

.btn-login {
    background-color: #0095f6;
    color: #fff;
    transition: all 0.5s ease;
    font-weight: 600;
}

.btn-login:hover {
    opacity: 0.8;
}
Style-Header.css

Ta sử dụng App.css làm file css chung cho toàn bộ page của chúng ta, tức là có cái style nào mà dùng đi dùng lại hoặc dùng cho toàn bộ trang thì ta quăng ở đó 🤭.

CSS

body {
    background-color: #fafafa;
}
App.css

Đây là thành quả của chúng ta 😁.

II. Tạo bài post cho app

Các bạn cũng có thể thấy là trong instagram có rất nhiều bài post theo thứ tự mới nhất đến cũ nhất, mỗi bài post như vậy ta gọi là một PostItem. Trong phần này ta sẽ tạo một PostItem để hiển thi một post mẫu nhé 😉.

Đây là một PostItem mẫu mình trích từ instagram của mình, những phần mình khoanh đỏ trong hình ảnh chính là những thứ mà chúng ta sẽ làm nhé còn lại chúng ta chưa quan tâm lúc này.

Trong folder components tạo thêm một folder tên PostItem và trong nó tạo thêm 2 file PostItem.jsxStyle-PostItem.css. Tạo xong nhớ implement code import file css vào nhé 😁.

Cấu trúc của một bài Post như sau:

Structure of post item

Phần Avatar chúng ta sử dụng material-ui nhá, để cài đặt bạn vào đây để copy lệnh cài đặt cũng như đọc docs của nó nếu có hứng thú nhé 😉 copy xong paste vào terminal để cài đặt.

Trong src, tạo thêm folder assets để chứa image mà bạn muốn nhé, để có thể sử dụng ta tạo file ImageList.jstrong src rồi copy code như bên dưới, mỗi lần dùng thì chỉ cần import vào và dùng thôi nhé 😉.

JS

import AVATAR from './assets/avatar/avatar-01.jpg';
export {AVATAR};

Lưu ý: Ở đây ta chỉ test khi tạo một PostItem thôi, khi có data từ firebase thì ta sẽ sử dụng image từ firebase sau.

Trong PostItem.jsx các bạn code như bên dưới.

JS

import React from "react";
import "./Style-PostItem.css";
import { AVATAR, IMG_P_1 } from "../../ImageList";
import Avatar from "@material-ui/core/Avatar";

export default function PostItem() {
  return (
    <p className="post__container">
      {/* Header -> Username + Avatar + Local */}
      <p className="post__header">
        <p className="post__header--block-left">
          <p className="post__header--avatar">
            <Avatar alt="Remy Sharp" src={AVATAR} />
          </p>
        </p>
        <p className="post__header--block-right">
          <p className="post__header--username">
            <a href="/#">d_dev_guys</a>
          </p>
          <p className="post__header--more-option">
            <span>
              <i className="bx bx-dots-horizontal-rounded"></i>
            </span>
          </p>
        </p>
      </p>
      {/* image */}
      <p className="post__image">
        <img src={IMG_P_1} alt="p-1" />
      </p>
      <p className="post__group-bottom">
        {/* Group of interactive icons */}
        <p className="post__group-bottom">
          <p className="icons">
            <p className="icons-left">
              <span>
                <i className="bx bx-heart"></i>
              </span>
              <span>
                <i className="bx bx-message-rounded"></i>
              </span>
              <span>
                <i className="bx bx-paper-plane"></i>
              </span>
            </p>
            <p className="icons-right">
              <span>
                <i className="bx bx-bookmark"></i>
              </span>
            </p>
          </p>
          <p className="post__interactive-info">
            <a href="/#">
              <span>321</span> lượt thích
            </a>
          </p>
        </p>
        {/* Username + Caption */}
        <p className="post__caption">
          <p className="post__caption--user">
            <span className="user-name">
              <a href="/#">d_dev_guys</a>
            </span>
             
            <span className="caption">
              "Don't feel better than anybody, because you feel like something.
              Always have it at the back of your mind that you were nothing
              before you became something, and that thing you supposed to be is
              absolutely nothing."
            </span>
          </p>
          {/* Time */}
          <p className="post__caption--time"><span>1</span> Ngày trước</p>
        </p>
        {/* input field for comment */}
        <p className="post__comment">
            <form>
                <span>
                    <i className='bx bx-smile'></i>
                </span>
                <input type="text" placeholder="Thêm bình luận..." />
                <button className="btn btn-post-comment">Đăng</button>
            </form>
        </p>
      </p>
    </p>
  );
}
PostItem.jsx

Phần css cho nó, ta làm như bên dưới.

CSS

.post__container {
    margin-bottom: 24px;
    border-radius: 3px;
    border: 1px solid #dbdbdb;
    margin-left: -1px;
    margin-right: -1px;
    background-color: #fff;
}

.post__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
    border-bottom: 1px solid #efefef;
}

.post__header--block-right {
    margin-left: 14px;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-grow: 1;
    flex-shrink: 1;
    overflow: hidden;
}

.post__header--username a {
    color: #262626;
    font-weight: 600;
}

.post__header--more-option i.bx-dots-horizontal-rounded {
    font-size: 20px;
    cursor: pointer;
}

.post__image {
    background-color: #efefef;
    display: block;
    width: 100%;
    overflow: hidden;
}

.post__image img {
    height: 100%;
    width: 100%;
    object-fit: cover;
}

.post__group-bottom {
    padding: 0 16px;
    margin-top: 4px; 
}


.icons {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.icons .bx {
    font-size: 28px;
    color: #262626;
    padding: 8px;
    cursor: pointer;
}

.icons-left span:first-child {
    margin-left: -8px;
}

.icons-right span {
    transition: all 0.5s ease;
}

.icons-right span:hover {
    opacity: 0.8;
}

.post__interactive-info {
    margin-bottom: 8px;
}

.post__interactive-info a {
    font-weight: 600;
    color: #262626;
    font-size: 14px;
}

.post__caption {
    padding: 0 16px;
}

.user-name a {
    color: #262626;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-left: 5px;
    margin-left: -5px;
    font-size: 14px;
}

.caption {
    font-size: 14px;
    font-weight: 400;
    color: rgb(85, 85, 85);
}

.post__caption--time {
    font-size: 10px;
    color: #8e8e8e;
    margin-bottom: 5px;
    text-transform: uppercase;
}

.post__comment {
    margin-top: 4px;
    border-top: 1px solid #efefef;
    color: #8e8e8e;
    max-height: 56px;
    padding: 13px 0;
}

.post__comment form {
    display: flex;
    align-items: center;
    justify-content: space-between;
 
}

.post__comment form input {
    width: 100%;
    height: 18px;
    padding: 9px;
    outline: none;
    border: none;
}

.btn-post-comment {
    background-color: transparent;
    color: #0095f6;
    font-weight: 600;
}
Style-PostItem.css

Đây là code trong App.js hiện tại của mình.

JS

import React from 'react'
import './App.css';
import Header from './components/Header/Header'
import PostItem from './components/PostItem/PostItem'

function App() {
  return <p className="App">
    {/* Header */}
    <Header/>
    {/* Posts */}
    <p className="Post__list">
      <PostItem />
    </p>
  </p>;
}

export default App;
App.js

Đây là css chung trong App.css hiện tại.

CSS

body {
    background-color: #fafafa;
}

a {
    text-decoration: none;
}

.Post__list {
    margin-top: 5rem;
    margin-left: 5rem;
    max-width: 614px;
    width: 100%;
    margin-right: 28px;
}
App.css

Và đây là thành quả nè 😋.

III. Tổng kết

Trong phần 2 này, mình đã hướng dẫn các bạn tạo phần header và bài post cho trang của chúng ta. Trong phần tiếp theo, chúng ta sẽ cùng nhau giải quyết chuyện render cả một đống các bài post nhưng thế nào, cách implement Firebase Database, cách truy cập Database, Authentication, và Storage từ Firebase nhé 😉.

Cảm ơn các bạn đã theo dõi, see u 😉!

Bài viết cùng chuyên mục
Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise
Công Nghệ

Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise

Trong bài viết này, 200Lab sẽ chia sẻ những trường hợp dễ...

Công Nghệ

So sánh Flutter vs React Native: Framework nào đáng học năm 2021

Điểm chung của Flutter, React Native đều là Cross-platform Mobile, build native...

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1
Công Nghệ

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1

Từ khi Internet ra đời, sự phát triển về các giao thức...

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!
Công Nghệ

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!

1. Client encode file (base64) rồi gởi về backend 200Lab đã từng...

Công Nghệ

React Native – Hướng dẫn làm việc với Polyline và Animated-Polyline trên Map

Vẽ đường đi trên bản đồ là một nghiệp vụ vô cùng...

Công Nghệ

Hybrid App và Native App: Những khác biệt to lớn

Bất cứ khi nào một công ty quyết định làm ứng dụng...

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới
Công Nghệ

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới

Đây là một kiến trúc cơ bản mà bất kì một người...

Công Nghệ

Tư duy kiến trúc thông qua các trò chơi mà rất nhiều bạn không biết

Tư duy kiến trúc là gì? Tư duy kiến trúc có thể...