Khám Phá React - win 911

| Jan 19, 2025 min read

21 tháng 11 năm 2024 | Máy tính

React là một thư viện JavaScript phía trước được phát triển bởi Facebook, dùng để xây dựng giao diện người dùng (UI - User Interface). Nó tập trung vào lớp xem (View), giúp các nhà phát triển có thể tạo ứng dụng trang đơn và giao diện phức tạp dựa trên thành phần một cách hiệu quả hơn. Bài viết này sẽ giới thiệu về những khái niệm cơ bản của React và minh họa cách sử dụng các đặc điểm cơ bản thông qua ví dụ cụ thể.

1 React có những đặc điểm gì?

  • Thành phần hóa (Componentization):
    React chia nhỏ UI thành các thành phần nhỏ, có thể tái sử dụng. Mỗi thành phần có trạng thái riêng và logic hiển thị. Thành phần có thể lồng nhau và kết hợp lại để tạo cấu trúc trang. Có hai cách định nghĩa thành phần: thành phần chức năng (function components) và thành phần lớp (class components). Thành phần chức năng được khuyến khích vì chúng gọn nhẹ hơn và hỗ trợ Hooks.

  • DOM ảo (Virtual DOM):
    React sử dụng DOM ảo để tăng hiệu suất. Nó tạo ra một cây DOM ảo trong bộ nhớ, khi trạng thái hoặc dữ liệu thay đổi, React sẽ tính toán sự khác biệt giữa DOM ảo và DOM thực tế rồi tiến hành cập nhật DOM với mức tối thiểu. Cách tiếp cận này giảm thiểu việc thao tác trực tiếp vào DOM thực tế, cải thiện tốc độ hiển thị, đặc biệt hữu ích cho các giao diện phức tạp và thường xuyên cập nhật.

  • Dòng dữ liệu đơn hướng (One-way Data Flow):
    React áp dụng dòng dữ liệu đơn hướng, tức là dữ liệu di chuyển từ thành phần cha xuống con. Các thành phần con nhận dữ liệu thông qua props và không thể thay đổi trực tiếp trạng thái của cha. Trong mỗi thành phần, dữ liệu nội bộ được quản lý bằng trạng thái (state), có thể cập nhật thông qua hàm xử lý sự kiện, w9bet register kích hoạt quá trình hiển thị lại giao diện.

  • Cú pháp JSX:
    React sử dụng JSX (JavaScript XML) để mô tả cấu trúc UI. JSX là cú pháp giống HTML nhưng thực chất là mở rộng của JavaScript. JSX giúp viết cấu trúc UI trực quan hơn trong mã JavaScript, đồng thời cung cấp khả năng linh hoạt và dễ dàng kết hợp.

  • Hooks:
    Từ phiên bản 16.8, React giới thiệu Hooks, cho phép các thành phần chức năng sử dụng trạng thái và các tính năng khác như chu kỳ sống mà không cần đến lớp. Một số Hooks phổ biến bao gồm useState, useEffect, useContextuseReducer. Chúng giúp quản lý trạng thái và xử lý tác dụng phụ một cách gọn gàng hơn.

  • API Context:
    React cung cấp API Context để chia sẻ trạng thái giữa các thành phần trong cây thành phần mà không cần truyền props qua nhiều cấp. Đây là công cụ tuyệt vời cho việc quản lý trạng thái toàn cục như xác thực người dùng.

  • React Router:
    Mặc dù React không có chức năng định tuyến sẵn, bạn có thể sử dụng React Router để xử lý điều hướng giữa các trang mà không làm tươi lại toàn bộ trang.

  • Hiển thị phía máy chủ (SSR) và Tạo trang tĩnh (SSG):
    React có thể tích hợp với SSR như Next.js để cung cấp trải nghiệm tốt hơn về SEO và hiệu suất tải trang. Qua SSR, các thành phần React được tiền hiển thị trên máy chủ dưới dạng HTML, chỉ cần gắn kết sự kiện ở phía khách, tránh hiện tượng nhấp nháy và chậm trễ.

  • Quản lý trạng thái:
    Quản lý trạng thái trong React có thể thực hiện bằng cách sử dụng useState hoặc useReducer cho các ứng dụng đơn giản. Đối với các ứng dụng phức tạp, bạn có thể sử dụng thư viện bên ngoài như Redux, MobX hoặc Recoil để quản lý trạng thái toàn cầu.

  • Công cụ dành cho nhà phát triển:
    React cung cấp các công cụ mạnh mẽ như React DevTools, giúp bạn kiểm tra và tối ưu hóa quá trình hiển thị của thành phần, cũng như xem cấu trúc cây thành phần và trạng thái.

Tóm lại, React cung cấp cách tiếp cận linh hoạt, hiệu quả và dễ bảo trì để xây dựng các ứng dụng web hiện đại, với sự hỗ trợ mạnh mẽ từ hệ sinh thái phong phú.

2 Thực hành viết một ứng dụng mẫu

Tiếp theo, chúng ta sẽ xây dựng một ứng dụng thu thập blog đơn giản để minh họa cách sử dụng các tính năng cơ bản của React.

Ứng dụng blog này sẽ bao gồm 4 trang: trang chủ, danh sách blog, chi tiết blog và thêm blog. Kết quả sau khi win 911 hoàn thành sẽ trông như sau:

![Ứng dụng thu thập blog]

Các phiên bản Node.js, NPM và React được sử dụng như sau:

node: v20.17.0
npm: 10.8.2
react: 18.3.1

2.1 Tạo dự án mẫu

Trước khi bắt đầu lập trình, bạn cần sử dụng lệnh sau để tạo một dự án React mẫu chứa cấu trúc nền tảng.

npx create-react-app react-start-demo

Cấu trúc thư mục của dự án mẫu sẽ như sau:

react-start-demo/
├── public/
│   ├── index.html
│   └── favicon.ico
├── src/
│   ├── App.js
│   ├── App.test.js
│   ├── index.js
│   └── index.css
└── package.json

Sau đó, chúng ta sẽ sửa đổi cấu trúc này và bổ sung các thành phần mới.

2.2 Cấu trúc thư mục dự án

Để thực hiện ứng dụng blog, chúng tôi đã loại bỏ một số file thử nghiệm không cần thiết và thêm hai thư mục mới trong thư mục src: pagesutils. Thư mục pages chứa các thành phần trang, còn utils chứa các công cụ hỗ trợ.

Cấu trúc cuối cùng của dự án sẽ như sau:

react-start-demo/
├── public/
│   ├── index.html
│   └── favicon.ico
├── src/
│   ├── pages/
│   │   ├── HomePage.js
│   │   ├── BlogListPage.js
│   │   ├── BlogAddPage.js
│   │   ├── BlogDetailPage.js
│   │   └── NotFoundPage.js
│   ├── utils/
│   │   └── BlogStorageUtil.js
│   ├── App.js
│   ├── index.js
│   └── index.css
└── package.json

2.3 Phân tích mã nguồn chính

2.3.1 i88win index.html

File index.html nằm trong thư mục public là file HTML duy nhất của dự án React. Nó đóng vai trò là template chung, định nghĩa phần <head><body>, bao gồm menu đầu trang, thông tin chân trang và phần nội dung động được thay thế bởi React (<div class="container" id="root"></div>).

<!-- public/index.html -->
<!DOCTYPE html>
<html lang="vi">
 <head>
  <meta charset="utf-8" />
  <title>Tổng hợp Blog</title>
 </head>
 <body>
  <header>
   <nav>
    Trang chủ
    Thêm blog
    Danh sách blog
   </nav>
  </header>
  <div class="container" id="root"></div>
  <footer>
   <p>© 2024 Tổng hợp Blog</p>
  </footer>
 </body>
</html>

2.3.2 index.js

File index.js là điểm nhập chính của ứng dụng React.

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
 <React.StrictMode>
  <App />
 </React.StrictMode>
);

Tập tin này import React, ReactDOM và file CSS toàn cục, sau đó sử dụng ReactDOM để thay thế phần id="root" trong file index.html bằng thành phần <App />.

2.3.3 App.js

File App.js là file chính của ứng dụng, nơi chúng ta cấu hình tất cả quy tắc định tuyến.

// src/App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import HomePage from './pages/HomePage';
import BlogAddPage from './pages/BlogAddPage';
import BlogListPage from './pages/BlogListPage';
import BlogDetailPage from './pages/BlogDetailPage';
import NotFoundPage from './pages/NotFoundPage';
export default function App() {
 return (
  <Router>
   <Routes>
    <Route path='/' element={<HomePage />} />
    <Route path='/blogs/add' element={<BlogAddPage />} />
    <Route path='/blogs' element={<BlogListPage />} />
    <Route path='/blogs/:id' element={<BlogDetailPage />} />
    <Route path='*' element={<NotFoundPage />} />
   </Routes>
  </Router>
 );
}

2.3.4 File Utils

Ứng dụng này sử dụng localStorage của trình duyệt để lưu trữ dữ liệu và sử dụng một công cụ chuyên dụng BlogStorageUtil.js để quản lý đọc và ghi dữ liệu.

// src/utils/BlogStorageUtil.js
export function getAllBlogs() {
  const blogsStr = localStorage.getItem('blogs') || '[]';
  return JSON.parse(blogsStr);
}
export function addBlog(blog) {
  let blogs = getAllBlogs();
  blog.id = blogs.length + 1;
  blogs.push(blog);
  localStorage.setItem('blogs', JSON.stringify(blogs));
}
export function getBlogById(id) {
  return getAllBlogs().find((blog) => blog.id === id);
}

2.3.5 Thành phần trang

Chúng ta sẽ phân tích từng thành phần trang trong thư mục src/pages.

HomePage.js Thành phần này đại diện cho trang chủ của ứng dụng, nhiệm vụ đơn giản là thay đổi tiêu đề trang và hiển thị đoạn văn bản chào mừng.

// src/pages/HomePage.js
import { useEffect } from 'react';
export default function HomePage() {
  useEffect(() => {
    document.title = 'Trang chủ';
  }, []);
  return (
    <p>Chào mừng đến với tổng hợp blog, nơi hội tụ các blog chất lượng cao, giúp bạn đắm mình trong biển kiến thức!</p>
  );
}

BlogListPage.js Thành phần này hiển thị danh sách blog, lấy dữ liệu từ BlogStorageUtil và render dưới dạng danh sách.

// src/pages/BlogListPage.js
import { useEffect } from 'react';
import { getAllBlogs } from '../utils/BlogStorageUtil';
export default function BlogListPage() {
  useEffect(() => {
    document.title = 'Danh sách blog';
  }, []);
  const blogs = getAllBlogs();
  return (
    <div className="blog-list">
      <ul>
        {blogs.map((blog, index) => (
          <li key={index}>
            {blog.name}
          </li>
        ))}
      </ul>
    </div>
  );
}

BlogDetailPage.js Thành phần này hiển thị chi tiết của một blog cụ thể.

// src/pages/BlogDetailPage.js
import { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { getBlogById } from '../utils/BlogStorageUtil';
export default function BlogDetailPage() {
  let { id } = useParams();
  const blog = getBlogById(Number(id));
  useEffect(() => {
    document.title = blog.name;
  }, [blog]);
  return (
    <div className="blog-detail">
      <h2>{blog.name}</h2>
      <p>{blog.description}</p>
      <div className="note">{blog.technical ? '* Đây là blog kỹ thuật' : '* Đây là blog phi kỹ thuật'}</div>
    </div>
  );
}

BlogAddPage.js Thành phần này cho phép thêm blog mới, bao gồm form và xử lý validation.

// src/pages/BlogAddPage.js
import { useEffect, useState } from 'react';
import { addBlog } from '../utils/BlogStorageUtil';
function validateFormData(formData) {
  if (formData.name.length <= 2) {
    return { field: 'name', message: 'Tên blog phải lớn hơn 2 ký tự' };
  }
  if (formData.description.length <= 10) {
    return { field: 'description', message: 'Mô tả blog phải lớn hơn 10 ký tự' };
  }
  return null;
}
export default function BlogAddPage() {
  const [formData, setFormData] = useState({ name: '', description: '', technical: false });
  const [error, setError] = useState({});
  useEffect(() => {
    document.title = 'Thêm blog';
  }, []);
  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    const error = validateFormData(formData);
    if (null === error) {
      addBlog(formData);
      window.location = '/blogs';
    } else {
      setError(error);
    }
  };
  return (
    <div className="form">
      <form onSubmit={handleSubmit}>
        <div>
          <label>Tên blog:</label>
          {error.field === 'name' && <span className="error">{error.message}</span>}
        </div>
        <div>
          <input name="name" value={formData.name} onChange={handleChange} />
        </div>
        <div>
          <label> tả blog:</label>
          {error.field === 'description' && <span className="error">{error.message}</span>}
        </div>
        <div>
          <textarea name="description" value={formData.description} onChange={handleChange} />
        </div>
        <div>
          <label>Blog kỹ thuật:</label>
        </div>
        <div>
          <select id="options" name="technical" value={formData.technical} onChange={handleChange}>
            <option value="false">Không</option>
            <option value="true"></option>
          </select>
        </div>
        <div>
          <button>Gửi</button>
        </div>
      </form>
    </div>
  );
}

3 Kết luận

Như vậy, chúng ta đã giới thiệu các khái niệm cơ bản của React và thực hành xây dựng một ứng dụng thu thập blog để minh họa cách sử dụng các tính năng cơ bản của nó. Dự án mẫu đầy đủ đã được đẩy lên GitHub, mời bạn theo dõi hoặc Fork.

[1] React: Hướng dẫn nhanh
[2] React: Cài đặt
[3] React: Bắt đầu một dự án React mới
[4] React: Thêm React vào dự án hiện tại

![](Hình ảnh)

#React #JavaScript #Phát triển Frontend