<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Phúc Nguyễn</title>
    <description>The latest articles on DEV Community by Phúc Nguyễn (@nddev_18).</description>
    <link>https://dev.to/nddev_18</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2281137%2F3e62f772-c896-4a1d-8db3-a5875b1c237c.jpg</url>
      <title>DEV Community: Phúc Nguyễn</title>
      <link>https://dev.to/nddev_18</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nddev_18"/>
    <language>en</language>
    <item>
      <title>Tôi đã bắt đầu dùng TurboRepo từ con số 0</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Thu, 26 Feb 2026 07:23:45 +0000</pubDate>
      <link>https://dev.to/nddev_18/toi-da-bat-dau-dung-turborepo-tu-con-so-0-5f7c</link>
      <guid>https://dev.to/nddev_18/toi-da-bat-dau-dung-turborepo-tu-con-so-0-5f7c</guid>
      <description>&lt;h2&gt;
  
  
  Làm thế nào để bắt đầu?
&lt;/h2&gt;

&lt;p&gt;Trước tiên là cứ chạy một dự án mẫu lên để xem cấu trúc cái đã chứ tự cấu hình thì khó quá. &lt;br&gt;
Chạy lệnh:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;npx create-turbo@latest&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Sau khi chạy lệnh này thì sẽ có dự án mẫu&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxchyxf67qr7c5n26szws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxchyxf67qr7c5n26szws.png" alt=" " width="235" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sau khi có dự án mẫu chúng ta bắt đầu tìm hiểu về các khái niệm cơ bản:&lt;/p&gt;

&lt;h2&gt;
  
  
  Cấu trúc của dự án này như nào ?
&lt;/h2&gt;

&lt;p&gt;Đây là một dự án mono-repo với next js&lt;br&gt;
Cấu trúc chính: &lt;br&gt;
apps/          # Các ứng dụng và services&lt;br&gt;
packages/      # Thư viện, tooling và các package khác&lt;br&gt;
&lt;em&gt;Lưu ý: Không hỗ trợ các package lồng nhau nhiều cấp&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quản lý các dependencies như nào ?
&lt;/h2&gt;

&lt;p&gt;Có hai loại dependencies bao gồm: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;External dependencies&lt;/strong&gt;: Từ npm registry, giúp xây dựng ứng dụng và thư viện nhanh hơn&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal dependencies&lt;/strong&gt;: Chia sẻ chức năng trong repository, cải thiện khả năng khám phá và sử dụng code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ cài một External dependencies chung cho các dự án&lt;br&gt;
Nếu cả hai ứng dụng Next.js (ví dụ: apps/web và apps/docs) đều sử dụng lodash, bạn nên cài lodash ở cấp root của monorepo để dùng chung, giúp tiết kiệm dung lượng và đồng bộ phiên bản.&lt;br&gt;
chạy lệnh: &lt;br&gt;
&lt;code&gt;pnpm add lodash -w&lt;/code&gt;&lt;br&gt;
(-w hoặc --workspace-root để cài ở root)&lt;/p&gt;

&lt;p&gt;Ví dụ cài đặt một Internal dependencies&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw05v5q2yvjnyt91a80ah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw05v5q2yvjnyt91a80ah.png" alt=" " width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://turborepo.dev/docs/crafting-your-repository/creating-an-internal-package" rel="noopener noreferrer"&gt;https://turborepo.dev/docs/crafting-your-repository/creating-an-internal-package&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nếu bắt đầu với shadcn ui hãy làm theo hướng dẫn của tài liệu tại &lt;br&gt;
&lt;a href="https://ui.shadcn.com/docs/monorepo" rel="noopener noreferrer"&gt;https://ui.shadcn.com/docs/monorepo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>turborepo</category>
    </item>
    <item>
      <title>React Scan - Best choise for FE dev</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Thu, 30 Jan 2025 14:50:22 +0000</pubDate>
      <link>https://dev.to/nddev_18/react-scan-best-choise-for-fe-dev-1mnl</link>
      <guid>https://dev.to/nddev_18/react-scan-best-choise-for-fe-dev-1mnl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil41n9k212ump63pj0f0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil41n9k212ump63pj0f0.gif" alt="Image description" width="795" height="371"&gt;&lt;/a&gt;Bạn đã bao giờ gặp khó khăn trong việc kiểm soát đoạn mã của mình để tránh re-render giao diện lại một cách liên tục ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbg9o4g5arzkx2xrrq428.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbg9o4g5arzkx2xrrq428.png" alt="Image description" width="279" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Đã không ít lần bạn phải đau đầu tìm cho mình những lỗi sai ngớ ngẩn hoặc bất lực trong việc tìm lỗi chưa ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5lt51tmeg5eqjl8ia55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5lt51tmeg5eqjl8ia55.png" alt="Image description" width="395" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vậy thì bài viết ngày hôm nay tôi sẽ giới thiệu cho bạn một công cụ kiểm tra và gỡ lỗi vô cùng hiệu quả, giúp bạn tối ưu hoá hiệu suất cho trang web của mình mà không gặp nhiều khó khăn trong việc cài đặt và sử dụng.&lt;/p&gt;

&lt;p&gt;Đó chính là react-scan&lt;br&gt;
Bài viết sẽ bao gồm những nội dung chính bao gồm:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;React Scan là gì ?&lt;/li&gt;
&lt;li&gt;Lợi ích gì khi sử dụng react-scan ?&lt;/li&gt;
&lt;li&gt;React Scan hoạt động như nào ?&lt;/li&gt;
&lt;li&gt;Áp dụng react-scan vào bài toán thực tế &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Đầu tiên hãy cùng tìm hiểu&lt;/p&gt;

&lt;h2&gt;
  
  
  React-Scan là gì ?
&lt;/h2&gt;

&lt;p&gt;Hãy nói lời tạm biệt với việc trang web của bạn bị render chậm bắt đầu từ giây phút này. React-Scan là một công cụ "giám sát" và "chuẩn đoán" dành cho react. Chúng được thiết kế nhằm mục đích phân tích các vấn đề về hiệu suất và xác định các lần render không cần thiết. Việc ghi lại thông tin chi tiết về các chu kỳ render và tạo bản báo cáo có thể giúp bạn giải quyết vấn đề một cách hiệu quả.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lợi ích là gì ?
&lt;/h2&gt;

&lt;p&gt;Việc phải ngồi hàng giờ console.log("re-render") chắc hẳn đã từng làm cho rất nhiều ae dev phải đau đầu mất ngủ. Vì thế có thể thấy ngay react-scan sẽ giúp ae tiết kiệm công sức của mình đi rất nhiều trong những lần fix-bug.&lt;/p&gt;

&lt;p&gt;Cùng với đó, thay vì đoán và kiểm tra bug từng trang thì giờ đây ae không cần phải mất công như vậy. React-scan được tích hợp sẵn trên dự án và tự động thông báo trực tiếp lên trên giao diện cho anh em thấy những component nào đang có hiệu suất kém và cần cải thiện.&lt;/p&gt;

&lt;p&gt;Ngoài ra react-scan còn mô tả chi tiết cấu trúc component dù cho có cồng kềnh đến đâu, giúp cho lập trình viên không cần phải mất thời gian quá nhiều để mò mẫm, giúp cho họ biết được chỗ nào cần callback, chỗ nào cần memo.&lt;/p&gt;

&lt;h2&gt;
  
  
  React-scan hoạt động như nào ?
&lt;/h2&gt;

&lt;p&gt;Việc cài đặt thêm một công cụ vào project của mình nhằm nâng cao chất lượng code là tốt. Tuy nhiên chúng ta cùng cần phải nắm được rõ cách thức hoạt động của chúng như nào để đảm bảo tính bảo mật cho dự án.&lt;/p&gt;

&lt;p&gt;React-Scan hoạt động bằng cách "quét" ứng dụng React của bạn và ghi lại các chu kỳ render của từng thành phần. Dựa trên các thông số hiệu suất, nó sẽ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Xác định các thành phần bị ảnh hưởng.&lt;/strong&gt;
Những thành phần nào đang render quá thường xuyên hoặc không cần thiết sẽ được làm nổi bật.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hiển thị trực quan.&lt;/strong&gt;
Bạn sẽ thấy trực tiếp các thành phần "có vấn đề" được đánh dấu trong giao diện người dùng.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gợi ý cải thiện.&lt;/strong&gt;
Dựa trên thông tin thu thập được, bạn có thể xác định được khi nào cần tối ưu bằng các công cụ như React.memo, useCallback, hoặc các kỹ thuật quản lý state hiệu quả hơn.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Áp dụng react-scan vào bài toán thực tế
&lt;/h2&gt;

&lt;p&gt;Ok, giới thiệu công cụ xịn là vậy nhưng ví dụ thực tế cần phải hiệu quả thì mới đáng dùng. Cùng đi vào ví dụ một với một dự án thực tế của tôi.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztpyg7zh5jnclvje1uyh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztpyg7zh5jnclvje1uyh.gif" alt="Image description" width="795" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ứng dụng này sử dụng Next.js để tạo ra một trang web tương tác với các tính năng chính:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Thay đổi giao diện (theme)&lt;/strong&gt;: Người dùng có thể nhập các giá trị như "blue", "green", "dark" để thay đổi giao diện.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nút tăng số đếm&lt;/strong&gt;: Khi bấm vào nút, số đếm được cập nhật ngay lập tức.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phát hiện sự kiện nhấn vào vùng chính&lt;/strong&gt;: Khi người dùng nhấn vào khu vực nội dung, hệ thống sẽ hiển thị thông báo tương tác.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tương tác với footer&lt;/strong&gt;: Khi nhấn vào footer, một dòng thông báo sẽ xuất hiện.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Và bạn có thể thấy react scan hoạt động như ở trên hình. Tôi đã bật chức năng giám sát cho Footer và bạn có thể thấy tôi đã cố tình code lỗi để mỗi lần nhập vào input thì toàn bộ giao diện sẽ bị re-render lại và Footer cũng vậy. &lt;br&gt;
Theo nguyên tắc Footer là một component tĩnh và nó phải được memo để tránh các lần re-render không cần thiết như vậy.&lt;/p&gt;

&lt;p&gt;Tiếp theo hãy đến với một ví dụ khác:&lt;br&gt;
Ở ví dụ này tôi sẽ setup để react scan có thể ghi chép lại các thao tác của người dùng trên trang web cùng các số liệu để admin có thể phân tích hiệu năng thao tác.&lt;/p&gt;

&lt;p&gt;Đầu tiên hãy đăng nhập vào trang web &lt;a href="https://dashboard.react-scan.com/login" rel="noopener noreferrer"&gt;https://dashboard.react-scan.com/login&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tiếp theo đó tạo một project &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmovgoo43l4tjl01qo3vb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmovgoo43l4tjl01qo3vb.png" alt="Image description" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sau đó làm theo các bước hướng dẫn để tích hợp React Scan Monitoring vào dự án của mình.&lt;br&gt;
Sau đó quay trở lại trang web và thao tác khiến trang web re-render lại nhiều lần.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqfwsq78r0vai0994dlq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqfwsq78r0vai0994dlq.png" alt="Image description" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Truy cập lại trang dashboard monitor bạn sẽ thấy log của thao tác:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fviovyuxjgxs1chqics45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fviovyuxjgxs1chqics45.png" alt="Image description" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click chọn một thao tác và ta có bảng phân tích như sau:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgicx9zhmlm3g02i4eo5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgicx9zhmlm3g02i4eo5.png" alt="Image description" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Như vậy qua hai ví dụ chúng ta có thể thấy react-scan có thể tích hợp và sử dụng dễ dàng một cách hiệu quả trong project của chúng ta.&lt;br&gt;
Mong rằng bài viết của tôi sẽ giúp các bạn biết thêm được một công cụ mới mạnh mẽ trong việc tối ưu hoá cho trang web của mình. Chúc các bạn cài đặt và sử dụng thành công.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Toán tử ?= trong java script</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Thu, 16 Jan 2025 15:49:39 +0000</pubDate>
      <link>https://dev.to/nddev_18/toan-tu-trong-java-script-1e0o</link>
      <guid>https://dev.to/nddev_18/toan-tu-trong-java-script-1e0o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7vf1dexvw2837pcovs3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7vf1dexvw2837pcovs3.png" alt="Image description" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JavaScript giới thiệu một toán tử mới, &lt;code&gt;?=&lt;/code&gt; được gọi là toán tử gán an toàn. Toán tử này được thiết kế để đơn giản hóa việc xử lý lỗi trong đoạn mã của bạn, giúp bạn có đoạn mã dễ đọc và dễ xử lý hơn, đặc biệt là khi xử lý các hàm bắt lỗi try-catch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Toán tử ?= có tác dụng gì ?
&lt;/h2&gt;

&lt;p&gt;Khi bạn sử dụng &lt;code&gt;?=&lt;/code&gt;toán tử, nó sẽ kiểm tra xem một hàm hoặc thao tác có thành công hay không. Nếu thành công nó sẽ trả về kết quả. Nếu thất bại, nó sẽ trả về lỗi mà không làm sập chương trình của bạn.&lt;/p&gt;

&lt;p&gt;Sau đây là cách thức hoạt động của nó:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [error, result] ?= await fetch("https://dev.to/nddev_18/toan-tu-trong-java-script-1fl-temp-slug-9804469/edit")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Nếu như fetch thành công dữ liệu, &lt;code&gt;error&lt;/code&gt; sẽ mang giá trị &lt;code&gt;null&lt;/code&gt; và &lt;code&gt;result&lt;/code&gt; sẽ là data&lt;/li&gt;
&lt;li&gt;Nếu như fetch lỗi thì &lt;code&gt;error&lt;/code&gt; sẽ là chi tiết lỗi còn &lt;code&gt;result&lt;/code&gt; sẽ là &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qua ví dụ bạn sẽ thấy được những lợi ích cụ thế:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Xử lý lỗi đơn giản&lt;/strong&gt;: Bạn sẽ không còn cần những cú pháp try-catch dài ngoằng khi gọi api nữa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Code&lt;/strong&gt;: Đoạn mã của bạn sẽ dễ dàng để đọc và hiểu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hành vi nhất quán&lt;/strong&gt;: Cung cấp một cách xử lý lỗi một cách nhất quán trong đoạn mã của bạn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ cụ thể hơn nữa trong việc xử lý lỗi khi call API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fetch error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;jsonError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jsonData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JSON error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jsonError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jsonData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Đó chính là cách đơn giản để dùng toán tử &lt;code&gt;?=&lt;/code&gt; để xử lý lỗi như một bước tiếp theo của đoạn code tuần tự giúp đoạn mã trở nên đơn giản và dễ đọc hơn rất nhiều.&lt;/p&gt;

&lt;p&gt;Cuối cùng tổng kết lại:&lt;br&gt;
&lt;em&gt;Toán tử gán an toàn ?= là một công cụ mạnh mẽ dành cho các nhà phát triển JavaScript, đặc biệt là những người muốn viết mã rõ ràng, đáng tin cậy và có thể bảo trì. Bằng cách đơn giản hóa việc xử lý lỗi, nó giúp ngăn ngừa các sự cố không mong muốn và làm cho mã của bạn mạnh mẽ hơn. Nếu bạn đang làm việc với các lời hứa, hàm không đồng bộ hoặc bất kỳ thứ gì có thể gây ra lỗi, hãy thử toán tử ?=!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cảm ơn các bạn và chúc các bạn một ngày năng lượng !&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>37 Tip dành cho sự nghiệp của Frontend Develop (P2)</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Wed, 15 Jan 2025 15:56:40 +0000</pubDate>
      <link>https://dev.to/nddev_18/37-tip-danh-cho-su-nghiep-cua-frontend-develop-p2-ki3</link>
      <guid>https://dev.to/nddev_18/37-tip-danh-cho-su-nghiep-cua-frontend-develop-p2-ki3</guid>
      <description>&lt;p&gt;&lt;strong&gt;Cre: _ndeyefatoudiop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kết thúc phần 1 với 20 mẹo, mình xin được tóm tắt lại: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hãy nắm chắc những thứ cơ bản&lt;/li&gt;
&lt;li&gt;Hiểu được website hoạt động như nào&lt;/li&gt;
&lt;li&gt;Hãy làm quen với cấu trúc dữ liệu và thuật toán&lt;/li&gt;
&lt;li&gt;Hãy học bằng cách thực hành thay vì chỉ đọc và xem&lt;/li&gt;
&lt;li&gt;Hãy hỏi khi gặp vấn đề&lt;/li&gt;
&lt;li&gt;Tuy nhiên không phải lúc nào cũng đi hỏi người khác&lt;/li&gt;
&lt;li&gt;Dừng ngay việc copy paste những đoạn mã mà bạn thực sự không hiểu rõ&lt;/li&gt;
&lt;li&gt;Đừng vội tin vào những lời khuyên từ trên mạng&lt;/li&gt;
&lt;li&gt;Tư duy tích cực thay vì giấu đi sai lầm của bản thân&lt;/li&gt;
&lt;li&gt;Làm nó chạy trước khi tối ưu nó hoàn hảo&lt;/li&gt;
&lt;li&gt;Hãy học cách chia nhỏ công việc và quản lý chúng&lt;/li&gt;
&lt;li&gt;Luôn hoàn thành nhiệm vụ để có được sự tin tưởng tuyệt đối&lt;/li&gt;
&lt;li&gt;Hãy đam mê, hãy nhiệt tình với những thứ mình làm&lt;/li&gt;
&lt;li&gt;Luôn sẵn sàng học hỏi những điều mới.&lt;/li&gt;
&lt;li&gt;Master công cụ phát triển của bạn&lt;/li&gt;
&lt;li&gt;Tập trung phát triển ra sản phẩm giá trị&lt;/li&gt;
&lt;li&gt;Hãy học cách quảng bá sản phẩm của mình ?&lt;/li&gt;
&lt;li&gt;Thích viết mã thể hiện thông minh ?&lt;/li&gt;
&lt;li&gt;Người quản lý của bạn là đồng minh tốt nhất của bạn&lt;/li&gt;
&lt;li&gt;Hãy giúp đỡ quản lý của bạn&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Các bạn có thể xem lại cụ thể hơn qua bài viết: &lt;br&gt;
&lt;a href="https://dev.to/nddev_18/37-tip-danh-cho-su-nghiep-cua-frontend-develop-p1-4off"&gt;https://dev.to/nddev_18/37-tip-danh-cho-su-nghiep-cua-frontend-develop-p1-4off&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Còn bây giờ cùng nhau tiếp tục phần 2 với 17 mẹo còn lại:&lt;/p&gt;

&lt;h2&gt;
  
  
  21. Hãy hiểu bức tranh toàn cảnh đằng sau nhiệm vụ được giao
&lt;/h2&gt;

&lt;p&gt;Đừng chỉ chăm chăm vào code như một cái máy mà không suy nghĩ sâu xa&lt;br&gt;
Cụ thể hơn: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hiểu tại sao công việc đó có giá trị&lt;/strong&gt;: Công việc bạn đang làm có đóng góp gì cho mục tiêu chung ?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hiểu tại sao bạn lại được giao nhiệm vụ đó&lt;/strong&gt;: Bạn được chọn do năng lực, kỹ năng hay vai trò gì ?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hiểu công việc đó phù hợp như thế nào trong công ty&lt;/strong&gt;: Công việc bạn đang làm hỗ trợ mục tiêu lớn hơn của tổ chức ra sao ?
Việc nắm bắt được các khía cạnh này không chỉ giúp bạn làm việc hiệu quả hơn mà còn là chìa khoá để bạn phát triển và thăng tiến trong sự nghiệp&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  22. Hãy đóng góp team(doc, tech talk, demo, etc.)
&lt;/h2&gt;

&lt;p&gt;Điều này không chỉ có lợi ích cho công ty mà còn cho bạn.&lt;br&gt;
Bằng cách tiến hành các bản demo hoặc thuyết trình tài liệu, bạn sẽ thể hiện được kỹ năng của mình và nâng cao hiệu suất của nhóm.&lt;br&gt;
Luôn đặt mục tiêu nâng cao hiệu suất của nhóm bạn nhiều nhất có thể: điều đó thật thú vị và bổ ích&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhezqa99y9tr5d6bb07il.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhezqa99y9tr5d6bb07il.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  23. Hãy trở thành người được tin tưởng nhất trong một lĩnh vực cụ thể
&lt;/h2&gt;

&lt;p&gt;Thời gian đầu sự nghiệp bạn có thể thử nghiệm khám phá các lĩnh vực khác nhau để khám phá sở thích và năng lực của mình.&lt;br&gt;
Tuy nhiên để tiến xa hơn bạn cần tập trung chuyên môn sâu trong một lĩnh vực cụ thể. Điều này sẽ khiến bạn nổi bật và đáng giá hơn so với việc cái gì cũng biết một ít.&lt;br&gt;
Mục tiêu của bạn là xây dựng kỹ năng hình chữ T&lt;br&gt;
Ngang (broad knowledge): Có kiến thức cơ bản và nhiều lĩnh vực liên quan.&lt;br&gt;
Dọc (deep expertise): Có chuyên môn sâu trong một lĩnh vực cụ thể&lt;/p&gt;

&lt;h2&gt;
  
  
  24. Phát triển kỹ năng giao tiếp của bạn
&lt;/h2&gt;

&lt;p&gt;Thật không may đây là điều bắt buộc.&lt;br&gt;
Giao tiếp là đặc biệt quan trọng với các nhà phát triển. Chúng ta thường phải làm như sau: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RFCs(Request for Comments)&lt;/li&gt;
&lt;li&gt;Demos&lt;/li&gt;
&lt;li&gt;Presentations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vì vậy hãy chăc chắn bạn có trình độ giao tiếp cơ bản, thậm chí là nhiều ngôn ngữ khác nhau.&lt;/p&gt;

&lt;h2&gt;
  
  
  25. Nghỉ ngơi khi bạn gặp phải một vấn đề
&lt;/h2&gt;

&lt;p&gt;Thật khó khi bạn chìm sâu vào một vấn đề. Một lập trình viên 5 năm đôi khi cũng chưa thể rèn luyện cho mình một thói quen hoàn toàn như vậy.&lt;br&gt;
Tuy nhiên có một sự thật, sẽ luôn có những ý tưởng mới thông minh hơn sau mỗi lần nghỉ ngơi. Vì vậy hãy rời đi nếu như mắc kẹt quá lâu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8oru6dijmwwsu7ogp8j2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8oru6dijmwwsu7ogp8j2.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  26. Tập trung vào điểm mạnh
&lt;/h2&gt;

&lt;p&gt;Đừng cố lãng phí thời gian và năng lượng của mình vào điểm yếu mà bạn không giỏi.&lt;br&gt;
Đừng cố sửa chữa những điểm yếu lớn: &lt;br&gt;
Nếu bạn mất hơn 1 giờ để hoàn thành một nhiệm vụ mà đồng nghiệp chỉ cần 5' thì điều đó cho thấy đó không phải là lĩnh vực mà bạn tập trung.&lt;br&gt;
Dù cho có cố gắng nhiều, bạn cũng khó trở nên xuất sắc ở đó.&lt;br&gt;
Thay vào đó, hãy tối ưu hoá điểm mạnh của bạn. Làm tốt những thứ bạn giỏi và tự nhiên. Nếu điều bạn giỏi có giá trị với công việc và tổ chức, hãy dành nhiều thời gian cho nó hơn để tạo ra sự khác biệt.&lt;br&gt;
Hãy làm những điều xuất sắc hơn, điều đó sẽ mang lại hiệu quả giá trị cao hơn cho sự nghiệp của bạn thay vì cố gắng "bơi ngược dòng".&lt;/p&gt;

&lt;h2&gt;
  
  
  27. Làm chủ con đường sự nghiệp của bạn.
&lt;/h2&gt;

&lt;p&gt;Không ai sẽ lập kế hoạch cho sự nghiệp của bạn ngoài bạn.&lt;br&gt;
Nếu không có kế hoạch làm việc, bạn sẽ phải làm việc theo kế hoạch của người khác.&lt;br&gt;
Vì vậy hãy đảm bảo bạn sẽ có kế hoạch để đạt được những điều mà mình muốn trong 1/2/5 năm sau.&lt;/p&gt;

&lt;h2&gt;
  
  
  28. Kết giao cùng những đồng nghiệp
&lt;/h2&gt;

&lt;p&gt;Có rất nhiều lập trình viên trên thế giới và họ đều mang đến những điều tốt đẹp dành cho bạn: &lt;br&gt;
Bạn có thể học các thủ thuật và mẹo từ họ.&lt;br&gt;
Bạn có thể thảo luận về những kinh nghiệm được chia sẻ&lt;br&gt;
Bạn có thể nhờ giúp đỡ trong công việc&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxq883tlx6zyy91hyslnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxq883tlx6zyy91hyslnr.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  29. Hướng dẫn những người trẻ
&lt;/h2&gt;

&lt;p&gt;Đây là lúc bạn nhận ra bạn thông minh hơn bạn nghĩ nhiều.&lt;br&gt;
Việc hiểu và chia sẻ truyền đạt thành công cho một người khác giường như là một thành công.&lt;br&gt;
Bạn sẽ trở thành một người biết nhiều và khẳng định vị thế của mình trong mắt người khác&lt;/p&gt;

&lt;h2&gt;
  
  
  30. Sẵn sàng đối mặt với tất cả các vấn đề
&lt;/h2&gt;

&lt;p&gt;Việc giải quyết các vấn đề đa dạng khác nhau giúp cho bạn có được một cái nhìn trực quan hơn khi giải quyết các vấn đề khác. Bạn sẽ so sánh được nhiều cách giải cũng như buildup cho bản thân bộ kỹ năng fix bug hoàn hảo hơn.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7aibibbqadsw970eoatj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7aibibbqadsw970eoatj.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  31. Tìm kiếm cho bạn một người hướng dẫn
&lt;/h2&gt;

&lt;p&gt;Có một người hướng dẫn tốt sẽ là điểm nhấn cho sự nghiệp của bạn hơn.&lt;br&gt;
Mentor có thể giúp bạn phát triển hơn giống như việc họ hiểu về hành trình của bạn.&lt;br&gt;
Họ sẽ hướng dẫn bạn tránh khỏi những cái sai lầm mà họ đã gặp phải.&lt;/p&gt;

&lt;p&gt;Vậy làm thế nào để tìm được một mentor ?&lt;br&gt;
Kết nối với nhiều lập trình viên mà bạn đã từng tương tác, hỏi họ những câu hỏi, chia sẻ về những trải nghiệm với họ,...&lt;/p&gt;

&lt;h2&gt;
  
  
  32. Học sâu vào một framework cụ thể và làm chủ nó
&lt;/h2&gt;

&lt;p&gt;Framework là bộ công cụ hỗ trợ bạn đạt được mục tiêu một cách nhanh nhất.&lt;br&gt;
Vì vậy hãy bỏ qua một số tranh luận vô nghĩa trên mạng.&lt;br&gt;
Chọn một framework bạn cảm thấy thoải mái nhất để học, master nó, thế là đủ. Bằng việc nắm rõ các nguyên tắc cơ bản đề ra ở mẹo đầu tiên, việc chuyển sang sử dụng một framework nào đó là hoàn toàn dễ dàng.&lt;/p&gt;

&lt;h2&gt;
  
  
  33. Luôn đặt mình vào vị trí người dùng
&lt;/h2&gt;

&lt;p&gt;Ngay khi bản thiết kế nhận được hoặc task được giao bởi PM, bạn hãy cứ đặt mình vào ví trí người dùng và hãy đảm bảo trải nghiệm thật tốt. Với các mẹo tối ưu về hiệu năng thu thập được trong quá trình code bạn sẽ ngày càng nâng cao khả năng này lên.&lt;/p&gt;

&lt;h2&gt;
  
  
  34. Hãy thoải mái nói không
&lt;/h2&gt;

&lt;p&gt;Hãy biết chọn lựa và nói không với các nhiệm vụ không cần thiết để đảm bảo khối lượng công việc cho bản thân và hoàn thành các dự án một cách chất lượng nhất.&lt;/p&gt;

&lt;h2&gt;
  
  
  35. Liên tục học hỏi và trau dồi kỹ năng
&lt;/h2&gt;

&lt;p&gt;Với bất kỳ ai trong lĩnh vực công nghệ thông tin việc này là hoàn toàn bình thường. Hãy đầu tư thời gian cho việc học để tồn tại được trong ngành này lâu dài hơn.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1e7b48zznp7u0zckwvfp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1e7b48zznp7u0zckwvfp.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  36. Khi phải đối mặt với rất nhiều công việc, hãy chọn giảm thiểu tính năng thay vì giảm chất lượng code.
&lt;/h2&gt;

&lt;p&gt;Nhiều chức năng ư ? Điều đó có làm ứng dụng tốt hơn không ?&lt;br&gt;
Ban đầu việc một ứng dụng có thể đáp ứng được nhiều tính năng để nâng cao trải nghiệm người dùng. Tuy nhiên hãy thử tưởng tượng những tính năng đó được xây dựng bằng những dòng mã bẩn và bạn sẽ phải maintain nó lại một lần nữa. Ôi trời thật kinh khủng !!!&lt;/p&gt;

&lt;h2&gt;
  
  
  37. Luôn tôn trọng những người phối hợp trong dự án cùng bạn
&lt;/h2&gt;

&lt;p&gt;Luôn luôn dành sự tôn trọng tuyệt đối với nhiều ngành nghề khác nhau bởi vì không có họ sẽ không có thành quả tuyệt vời đó đâu. Phát triển ứng dụng là một nỗ lực của cả nhóm ! Hãy luôn nhớ như vậy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpi4mljspdpr0j504g27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpi4mljspdpr0j504g27.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;br&gt;
Như vậy trên đây là những mẹo mà một lập trình viên nước ngoài chia sẻ lại trên diễn đàn mà mình đã thu thập và dịch lại. Cảm ơn các bạn đã đọc bài viết này và đừng quên cho mình một tym nhé. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>37 Tip dành cho sự nghiệp của Frontend Develop (P1)</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Tue, 14 Jan 2025 16:02:26 +0000</pubDate>
      <link>https://dev.to/nddev_18/37-tip-danh-cho-su-nghiep-cua-frontend-develop-p1-4off</link>
      <guid>https://dev.to/nddev_18/37-tip-danh-cho-su-nghiep-cua-frontend-develop-p1-4off</guid>
      <description>&lt;p&gt;&lt;strong&gt;Cre: _ndeyefatoudiop&lt;/strong&gt;&lt;br&gt;
Trong tuần vừa rồi mình có đọc được một bài chia sẻ khá hay trên devto của một programer nước ngoài. Nội dung có nói về 37 mẹo mà anh đó thu thập được trong quá trình phát triển trở thành một senior frontend. Mình xin phép được chia sẻ lại với anh/em bằng tiếng việt cũng như một lần nữa note lại những kinh nghiệm quý báu cho bản thân.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Hãy nắm chắc những thứ cơ bản
&lt;/h2&gt;

&lt;p&gt;Một ngôi nhà được xây trên một nền móng không chắc chắc sẽ bị sụp đổ chỉ bởi những vấn đề nhỏ nhất. Điều tương tự sẽ xảy ra khi bạn không có kiến thức cơ bản chắc chắn: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bạn sẽ gặp khó khăn với những nền tảng framework&lt;/li&gt;
&lt;li&gt;Bạn sẽ mắc kẹt bởi những vấn đề lạ trong lần đầu tiên&lt;/li&gt;
&lt;li&gt;Bạn sẽ không tìm được cách giải quyết chung giữa những vấn đề.
Vì vậy bước đầu tiên để trở thành một Frontend Developer chuyên nghiệp, bạn phải master được HMTL, CSS, JS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Hiểu được website hoạt động như nào
&lt;/h2&gt;

&lt;p&gt;Sự phát triển không ngừng của công nghệ đã làm cho frontend cũng trở nên phức tạp hơn trong vài năm qua. &lt;br&gt;
Hàng ngàn tools, framework đã được ra đời và sử dụng rộng rãi&lt;br&gt;
Nếu như không trang bị cho mình kiến thức về cách một website hoạt động bạn sẽ không thể hiểu được tại sao lại cần những công cụ hỗ trợ cho việc code web như vậy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68dmr0b70ag9nmzwn3z6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68dmr0b70ag9nmzwn3z6.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Hãy làm quen với cấu trúc dữ liệu và thuật toán
&lt;/h2&gt;

&lt;p&gt;Thường thì cấu trúc dữ liệu và giải thuật thường ít được chú ý đến, tuy nhiên hiện nay đã có nhiều công ty đưa chúng vào phỏng vấn. &lt;br&gt;
Vâng không sai đâu, để viết được những chương trình phức tạp bạn sẽ cần trang bị cho mình một bộ óc logic bằng cách nắm được các thuật toán cơ bản để xử lý vấn đề một cách thuần thục chủ động thay vì chỉ phụ thuộc vào AI.&lt;br&gt;
Đây là danh sách cơ bản nhất: &lt;br&gt;
Cấu trúc dữ liệu: Stack, Queue, Hashmap, Set, Graph, etc&lt;br&gt;
Giải thuật: Dynamic programming, Greedy algorithm, Recursion, etc&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Hãy học bằng cách thực hành thay vì chỉ đọc và xem
&lt;/h2&gt;

&lt;p&gt;Các video hướng dẫn dường như đánh lừa bạn rằng bạn đang tiến bộ.&lt;br&gt;
Hầu hết các nhà sản xuất video đều khiến bạn cảm thấy rằng bạn đang học và ngày một phát triển thêm, thế nhưng thực tế thì không hề. Việc học thật sự chỉ bắt đầu khi bạn gõ phím và chỉ lại cho người khác.&lt;br&gt;
Vì vậy hãy thực hành thật nhiều và dành lấy cách danh hiệu trong các khoá học.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Hãy hỏi khi gặp vấn đề
&lt;/h2&gt;

&lt;p&gt;Bạn không hề cô đơn đâu&lt;br&gt;
Có rất nhiều người có trình độ cao hơn bạn đang ở xung quanh bạn.&lt;br&gt;
Vì vậy đừng lãng phí thời gian cho những vấn đề vặt. Mục tiêu của bạn là cải thiện bản thân vì vậy đừng lãng phí thời gian cho những vấn đề mà người khác đã giải quyết nó.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6ses31f8v1xdna3flqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6ses31f8v1xdna3flqi.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Tuy nhiên không phải lúc nào cũng đi hỏi người khác
&lt;/h2&gt;

&lt;p&gt;Hãy đảm bảo rằng bạn thực sự thực hiện những yêu cầu dưới đây trước khi đem vấn đề đi gặp người khác: &lt;br&gt;
Search chưa ? Kĩ chưa ?&lt;br&gt;
Hiểu được mục đích của mình và biết được tại sao nó không hoạt động chưa ?&lt;/p&gt;

&lt;p&gt;Hãy cố ghi lại những vấn đề đã từng gặp và rồi hãy đem chúng đi hỏi nhé, và rồi hãy ghi nhớ lại câu trả lời giúp đỡ để không gặp phải vấn đề tương tự một lần nữa.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Dừng ngay việc copy paste những đoạn mã mà bạn thực sự không hiểu rõ
&lt;/h2&gt;

&lt;p&gt;Điều này thực sự rất tệ vì nhiều lý do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bạn sẽ gặp phải những đoạn mã không an toàn.&lt;/li&gt;
&lt;li&gt;Bạn sẽ không thể maintain chúng lần 2.&lt;/li&gt;
&lt;li&gt;Bạn sẽ không thể trình bày nó cho mentor của mình.
Điều này liên quan trực tiếp đến GPT vì đôi khi nó chỉ cung cấp câu trả lời chính xác đến 80%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrrpegdrolw39o3hefuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrrpegdrolw39o3hefuv.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Đừng vội tin vào những lời khuyên từ trên mạng
&lt;/h2&gt;

&lt;p&gt;Tôi đã gặp sai lầm khi tôi bắt đầu lập trình&lt;br&gt;
Tôi đã từng hiểu rằng việc ghi nhớ lại các biến trong React là không tốt vì vậy tôi đã ngừng sử dụng chúng. Điều này là sai lầm và tôi đã ghi nhớ mãi trong cuộc đời của mình. &lt;br&gt;
Vì vậy mỗi khi tôi thấy lời khuyên của ai đó trên mạng:&lt;br&gt;
Lời khuyên này có dành cho tôi không ?&lt;br&gt;
Tác giả có ở trong hoàn cảnh tương tự như tôi không ?&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Tư duy tích cực thay vì giấu đi sai lầm của bản thân
&lt;/h2&gt;

&lt;p&gt;Thông thường khi bạn là người mới, bạn thường nghĩ rằng mọi người đang chờ đợi sai lầm của bạn để chỉ trích bạn, sa thải bạn. &lt;br&gt;
Thực tế nó ngược lại hoàn toàn, khi một người anh, một người sếp thuê tôi họ rất muốn tôi thành công nếu không họ sẽ cảm thấy lãng phí nguồn lực tài chính mà họ đã đầu tư vào tôi.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Làm nó chạy trước khi tối ưu nó hoàn hảo
&lt;/h2&gt;

&lt;p&gt;Việc theo đuổi mọi thứ hoàn hảo dường như là không thể: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sự trì hoãn&lt;/li&gt;
&lt;li&gt;Lãng phí thời gian&lt;/li&gt;
&lt;li&gt;Sự quá phức tạp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vì vậy hãy xem xét kỹ nhé!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq560gg0l7ijhmfunw3dq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq560gg0l7ijhmfunw3dq.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Hãy học cách chia nhỏ công việc và quản lý chúng
&lt;/h2&gt;

&lt;p&gt;Điều này vô cùng quan trọng:&lt;br&gt;
Chúng sẽ giúp bạn tránh cảm giác choáng ngợp&lt;br&gt;
Cảm giác bạn luôn đi theo tiến độ của mình&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Luôn hoàn thành nhiệm vụ để có được sự tin tưởng tuyệt đối
&lt;/h2&gt;

&lt;p&gt;Hãy làm sao để chứng minh cho leader của bạn thấy được năng lực của bạn một cách rõ ràng để khi nhìn vào bạn họ có thể yên tâm và giao cho bạn những nhiệm vụ mà họ tin tưởng bạn có thể hoàn thành chúng tuyệt đối.&lt;br&gt;
Đừng làm cho leader của bạn phải thêm một công việc đó chính là giám sát việc làm của bạn nhé.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Hãy đam mê, hãy nhiệt tình với những thứ mình làm
&lt;/h2&gt;

&lt;p&gt;Bạn có tin không, bạn có thể bù đắp những khuyết điểm trong công việc của mình bằng sự nhiệt tình.&lt;br&gt;
Đặc biệt là những người mới, hãy thể hiện cảm xúc hào hứng và háo hức.&lt;br&gt;
Không ai muốn thúc ép ai làm việc. Việc kèm cặp đã khó khăn vô cùng rồi, việc phải động viên ai đó nữa thực sự là tồi tệ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1h7f1thdv8h8sup8fliu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1h7f1thdv8h8sup8fliu.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Luôn sẵn sàng học hỏi những điều mới.
&lt;/h2&gt;

&lt;p&gt;Điều này chắc chắn sẽ là triết lý vì thời đại công nghệ này cái gì cũng update liên tục!&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Master công cụ phát triển của bạn
&lt;/h2&gt;

&lt;p&gt;Chia sẻ cho bạn ít bí quyết để cải thiện tốc độ phát triển phần mềm&lt;br&gt;
Hãy hiểu và nắm rõ được:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IDE của bạn&lt;/li&gt;
&lt;li&gt;Source code mà bạn đang gõ&lt;/li&gt;
&lt;li&gt;Trình duyệt mà bạn đang sử dụng duyệt web&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97dgvmhk2uhl4opel37x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97dgvmhk2uhl4opel37x.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  16. Tập trung phát triển ra sản phẩm giá trị
&lt;/h2&gt;

&lt;p&gt;Đừng viết mã trong vô thức, hãy viết những đoạn mã thực sự có giá trị.&lt;br&gt;
Mỗi dòng mã bạn viết ra phải cung cấp giá trị cho: &lt;br&gt;
Khách hàng của bạn.&lt;br&gt;
Công ty của bạn.&lt;br&gt;
Các bên liên quan.&lt;br&gt;
Yên tâm việc hoàn thành tốt những mục đích dự án sẽ giúp bạn nhận được những giá trị không hề nhỏ đâu.&lt;/p&gt;

&lt;h2&gt;
  
  
  17. Hãy học cách quảng bá sản phẩm của mình ?
&lt;/h2&gt;

&lt;p&gt;Một sản phẩm tốt là một sản phẩm phải đến được tay nhiều người dùng.&lt;br&gt;
Bạn nói bạn làm được một sản phẩm tốt ?&lt;br&gt;
Vậy nó được ai dùng ? Không ai biết về nó haha...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs0phae3w109rm0omgih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs0phae3w109rm0omgih.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  18. Thích viết mã thể hiện thông minh ?
&lt;/h2&gt;

&lt;p&gt;Một nguyên tắc rõ ràng khi làm việc nhóm được xây dựng như sau: &lt;br&gt;
Khả năng đọc &amp;gt; Hiệu suất &amp;gt; Thông minh&lt;br&gt;
Hạn chế viết các đoạn mã thông minh đến nỗi chỉ mình bạn đọc được.&lt;br&gt;
Hãy viết những đoạn mã hiệu quả để đồng nghiệp còn có thể đảm nhiệm tốt đoạn mã của bạn.&lt;/p&gt;

&lt;h2&gt;
  
  
  19. Người quản lý của bạn là đồng minh tốt nhất của bạn
&lt;/h2&gt;

&lt;p&gt;Điều này dường như rất ít các lập trình viên nhận ra, trừ khi bạn thực sự không may mắn.&lt;/p&gt;

&lt;h2&gt;
  
  
  20. Hãy giúp đỡ quản lý của bạn
&lt;/h2&gt;

&lt;p&gt;Điều này dễ nhưng nó cũng giống như điều trên, các lập trình viên rất dễ bỏ qua điều đó.&lt;br&gt;
Đôi khi quản lý của bạn bị quá tải công việc. Việc giúp đỡ quản lý làm việc cũng là học hỏi những kinh nghiệm từ những đầu việc mới. Thậm chí nó còn giúp bạn dễ dàng cho các lần cần hỗ trợ khác.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrl79h5pojzhnjjkw0ns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrl79h5pojzhnjjkw0ns.png" alt="Image description" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Nên sử dụng Promise hay Async/await ?</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Tue, 24 Dec 2024 03:56:15 +0000</pubDate>
      <link>https://dev.to/nddev_18/nen-su-dung-promise-hay-asyncawait--l0d</link>
      <guid>https://dev.to/nddev_18/nen-su-dung-promise-hay-asyncawait--l0d</guid>
      <description>&lt;p&gt;Đã bao giờ bạn thắc mắc tại sao chúng ta đều có thể xử lý call API với Promise hoặc Async/await và call bằng cách nào thì thuận tiện hơn chưa ? &lt;br&gt;
Trước kia mình hay call bằng Promise khi bắt đầu học về fetch trong javascript và sau đó mình chuyển sang dùng async await khi bắt đầu học trong các khoá học. Mình chỉ nghĩ đơn giản đó là phong cách code của mỗi người dạy khác nhau nên nếu mình quen call bằng cái gì thì mình call như vậy. Cho đến một ngày mình mày mò tối ưu những dòng code mà mình gõ, mình chợt đặt ra câu hỏi  rằng "Dùng cách nào call thì sẽ tối ưu hơn nhỉ?"&lt;br&gt;
Đó cũng chính là lý do mà mình viết bài viết ngày hôm nay nhằm chia sẻ cho bạn về câu trả lời của mình cho câu hỏi này.&lt;/p&gt;

&lt;p&gt;Mình bắt đầu google search như sau "Có bất kỳ lợi ích nào về việc sử dụng Promise hơn async await?" và mình có đọc được một ví dụ rất hay như sau.&lt;br&gt;
Hãy bắt đầu&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TIME_PROCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;X&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TIME_PROCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;_y&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;chạy file và kết quả trả về&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3noqlbzyrb68h7k8ksti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3noqlbzyrb68h7k8ksti.png" alt="Image description" width="423" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Như vậy chúng ta phải mất 3s để hoàn thành việc tính toán cho phép cộng trên. Lý do là await sau đã bị phụ thuộc vào await trước.&lt;br&gt;
Tuy nhiên theo logic thực tế chúng ta sẽ bị sai, x và y là hai phương thức độc lập khác nhau, chúng ta không thể bắt y chờ cho x cũng như không thể bắt x chờ cho y để thực hiện phép tính.&lt;br&gt;
Đây chính là trường hợp chúng ta phải dùng Promise&lt;br&gt;
sửa lại đoạn code một chút &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3c7h1znwoh6vo296094.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3c7h1znwoh6vo296094.png" alt="Image description" width="638" height="253"&gt;&lt;/a&gt;&lt;br&gt;
Kết quả trả về chỉ còn&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuwufg1g04die0vqhurx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuwufg1g04die0vqhurx.png" alt="Image description" width="361" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hoặc chúng ta cũng có thể viết như này&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb4lask2yhlw43rkkurg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb4lask2yhlw43rkkurg.png" alt="Image description" width="702" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcpqtzfba7emyfvqm506.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcpqtzfba7emyfvqm506.png" alt="Image description" width="311" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kết quả trả về cũng chỉ còn 2s&lt;/p&gt;

&lt;p&gt;Như vậy các bạn đã tự rút ra được câu trả lời cho vấn đề mình đặt ra hồi đầu bài viết rồi chứ.&lt;br&gt;
Không phải theo phong cách người code mà chúng ta cần phải đặt vào từng trường hợp khác nhau. Chúng ta chỉ có thể sử dụng async await cho các tác vụ tuần tự còn độc lập thì phải dùng Promise để tối ưu rồi.&lt;/p&gt;

&lt;p&gt;Cuối cùng mình muốn bật mí cho các bạn thêm một phương thức rất hay có tên là Promise.allSettled, các bạn có thể tìm đọc thêm để có thêm kiến thức nhé.&lt;/p&gt;

&lt;p&gt;promise.all tương đương với const X = await promiseA + await promiseB + await promiseC; &lt;/p&gt;

&lt;p&gt;Chúc may mắn và thành công !&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Tôi sẽ không muốn tạo Table bằng bất cứ cách khác ?</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Tue, 24 Dec 2024 03:10:56 +0000</pubDate>
      <link>https://dev.to/nddev_18/toi-se-khong-muon-tao-table-bang-bat-cu-cach-khac--12d4</link>
      <guid>https://dev.to/nddev_18/toi-se-khong-muon-tao-table-bang-bat-cu-cach-khac--12d4</guid>
      <description>&lt;p&gt;Xin chào mọi người, hôm nay lại là một bài viết về một lib quen thuộc mà mình hay sử dụng trong khi lập trình frontend.&lt;br&gt;
Có thể nói rằng Form và Table là hai thành phần con cực kỳ quan trọng và cũng không kém phần phức tạp trong lập trình giao diện Web. Với React JS chúng ta đã quá quen thuộc với ReactHookForm, vậy còn với Table chúng ta sẽ sử dụng lib nào ?&lt;/p&gt;

&lt;p&gt;Nếu như bạn đã từng nghe đến Tanstack chắc hẳn bạn sẽ từng nghe đến bộ kit open source chất lượng cao từ nhà phát triển này. Tanstack Table là một trong số đó. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tanstack Table là một Headless UI cho việc xây dựng và phát triển table một cách mạnh mẽ. Chính vì là Headless UI nên chúng vô cùng linh hoạt và nhẹ. Không có những thành phần UI cứng nhắc, thay vào đó chúng giúp ta xử lý các logic cốt lõi và thoả sức sáng tạo với giao diện mà chúng ta mong muốn. Đó cũng chính là lý do vì sao mà SHADCN UI khuyến khích user dùng Component Table của họ cùng với Tanstack Table.&lt;/li&gt;
&lt;li&gt;Lợi ích thứ 2 phải kể đến việc chúng đem lại hiệu suất làm việc rất cao.Thử tưởng tượng một bảng table của bạn có hàng ngàn bản ghi như excel, vậy cây DOM sẽ mất bao lâu để có thể load toàn bộ các cột hàng trong bảng. Với cơ chế ảo hoá được tích hợp kèm react-vitualization chúng ta có thể hiển thị dữ liệu lớn mà không lo ứng dụng bị chậm.&lt;/li&gt;
&lt;li&gt;Lợi ích thứ 3 đó chính là các chức năng phụ hỗ trợ đi kèm như: Sắp xếp, Phân trang, Lọc dữ liệu, Nhóm cột, Kéo thả. Thông thường các chức năng này nếu xử lý bằng mã thông thường, lập trình viên frontend phải mất hàng giờ để có thể hoàn tất.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sự hỗ trợ đa dạng ngôn ngữ cùng framework chính là lợi thế lớn nhất của Tanstack Table. &lt;/p&gt;

&lt;p&gt;Với một ví dụ đơn giản sau đây tôi có thể chỉ cho bạn cách làm quen và sử dụng với framework này.&lt;br&gt;
Tôi sẽ bỏ qua bước cài đặt môi trường vì nó khá đơn giản và quen thuộc với các lập trình viên.&lt;br&gt;
Giả dụ tôi đang có một bảng thống kê các hoạt động.&lt;br&gt;
Chúng ta sẽ chia cấu trúc thư mục như sau: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzn62btijqr3qhsyezp0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzn62btijqr3qhsyezp0.png" alt="Image description" width="300" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;File Column.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;columnsOverview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ColumnDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;accessorKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex items-end gap-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;getActionIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-gradient-to-r from-red-500 via-orange-300 to-yellow-200 size-[30px] border border-white p-2 rounded-full flex items-center justify-center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-[12px] text-white"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;accessorKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`day&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;size-[100px]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;getChainFire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File TableOverview.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TableOverview&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;TableOverviewProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getChainFireData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;transformChainData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReactTable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;getCoreRowModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getCoreRowModel&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;columnVirtualizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useVirtualizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;horizontal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;getScrollElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;estimateSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;overscan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableHeader&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHeaderGroups&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-[100px] border-none"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableHead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableHead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableHeader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableBody&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;" border-r border-[#4d86ab] "&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRowModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-[100px] border-t-0"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableCell&lt;/span&gt;
                                        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px-6 text-sm text-gray-700&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                            &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRowModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                                                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border-b  border-[#4d86ab]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                                                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
                                        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;flexRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                            &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVisibleCells&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                            &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVisibleCells&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableCell&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableBody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"overflow-x-auto overflow-y-hidden scroll-ct w-full"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
                        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;columnVirtualizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTotalSize&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;relative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableHeader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHeaderGroups&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-[100px] border-none"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;columnVirtualizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVirtualItems&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headerGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                            &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableHead&lt;/span&gt;
                                                    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                                        &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`translateX(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                        &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;absolute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-0 text-left text-sm font-semibold text-gray-600 justify-center"&lt;/span&gt;
                                                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-center flex-col gap-1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-[20px] font-normal text-[#4d86ab]"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;getDayOfWeek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                                    &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                                        &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
                                                                            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                                                                    &lt;span class="p"&gt;),&lt;/span&gt;
                                                                    &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                                                    &lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                                                &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
                                                                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;size-[60px] rounded-full bg-[#cb8989] items-center justify-center flex text-[30px] font-normal text-white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                                                                &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPlaceholder&lt;/span&gt;
                                                                    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
                                                                    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;flexRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                                          &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                                          &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                                                      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableHead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                            &lt;span class="p"&gt;)&lt;/span&gt;
                                        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableHeader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableBody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRowModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRowModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-[100px] border-b border-[#4d86ab]"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;columnVirtualizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVirtualItems&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVisibleCells&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                                &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableCell&lt;/span&gt;
                                                        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-0 w-[100px]"&lt;/span&gt;
                                                        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clicky&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                                            &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;virtualColumn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                            &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;absolute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;flexRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columnDef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableCell&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                                &lt;span class="p"&gt;)&lt;/span&gt;
                                            &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class="p"&gt;))&lt;/span&gt;
                                &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableCell&lt;/span&gt;
                                            &lt;span class="na"&gt;colSpan&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                                            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-4 py-4 text-center text-sm text-gray-500"&lt;/span&gt;
                                        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                            No data available
                                        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableCell&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableBody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Giải thích cho hai file code trên
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Định nghĩa cột trong bảng
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cột đầu tiên&lt;/strong&gt;: Là cột tiêu đề, không hiển thị dữ liệu mà chứa thông tin tiêu đề.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Các cột còn lại&lt;/strong&gt;: Hiển thị dữ liệu trong 30 ngày (từ &lt;code&gt;day1&lt;/code&gt; đến &lt;code&gt;day30&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Các thành phần chính:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;accessorKey&lt;/code&gt;&lt;/strong&gt;: Xác định dữ liệu từ &lt;code&gt;activity&lt;/code&gt; trong mảng dữ liệu.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;cell&lt;/code&gt;&lt;/strong&gt;: Render nội dung của ô cột, bao gồm biểu tượng (icon) và số liệu tổng (&lt;code&gt;value.total&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;JSON.parse&lt;/code&gt;&lt;/strong&gt;: Giải mã chuỗi JSON để hiển thị dữ liệu chi tiết.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getActionIcon(value.type)&lt;/code&gt;&lt;/strong&gt;: Hàm tạo biểu tượng phù hợp với loại hoạt động.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Xây dựng bảng và truyền dữ liệu
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;useReactTable&lt;/code&gt;&lt;/strong&gt;: Khởi tạo bảng từ dữ liệu và cột.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getCoreRowModel&lt;/code&gt;&lt;/strong&gt;: Quản lý mô hình hàng (&lt;code&gt;row model&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Ảo hóa cột với &lt;code&gt;useVirtualizer&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;horizontal: true&lt;/code&gt;&lt;/strong&gt;: Ảo hóa cột theo chiều ngang.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;count&lt;/code&gt;&lt;/strong&gt;: Số lượng cột (trừ cột &lt;code&gt;activity&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;estimateSize&lt;/code&gt;&lt;/strong&gt;: Kích thước cột khoảng &lt;strong&gt;100px&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;overscan&lt;/code&gt;&lt;/strong&gt;: Render thêm 5 cột ngoài vùng nhìn thấy để tránh lag khi cuộn.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Đây chỉ là một ví dụ đơn giản trong việc tạo bảng với tanstack table. Trong thực tế chúng ta còn có thể kết hợp rất nhiều các kỹ thuật khác nhau như đã liệt kê tại phần lợi ích bên trên. Chúng ta có thể sáng tạo rất nhiều trên lib này, nó là lib mà mình rất yêu thích. Chúc tất cả các bạn thành công.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Bạn đã biết đến Web-Vital ?😣</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Sat, 30 Nov 2024 14:34:05 +0000</pubDate>
      <link>https://dev.to/nddev_18/ban-da-biet-den-web-vital--45g9</link>
      <guid>https://dev.to/nddev_18/ban-da-biet-den-web-vital--45g9</guid>
      <description>&lt;h1&gt;
  
  
  Web Vitals là gì và tại sao bạn nên quan tâm?
&lt;/h1&gt;

&lt;p&gt;Là một lập trình viên, bạn đã từng nghe đến &lt;strong&gt;Web Vitals&lt;/strong&gt; chưa?&lt;br&gt;&lt;br&gt;
Nếu chưa, đây là một bài viết ngắn gọn mà mình sẽ chia sẻ lại cho bạn trên vai trò là một lập trình viên Frontend có chút kiến thức về tối ưu hoá nhé.&lt;br&gt;&lt;br&gt;
Let’s go!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0ia1f8myyhe45pgzg1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0ia1f8myyhe45pgzg1z.png" alt="Image description" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Web Vitals là gì?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Web Vitals&lt;/strong&gt; là một tập hợp các chỉ số của ông kẹ &lt;strong&gt;Google&lt;/strong&gt; dùng để đo lường trải nghiệm người dùng (UX) trên các trang web. Các chỉ số này được thiết kế để phản ánh các yếu tố quan trọng của trải nghiệm người dùng chẳng hạn như tốc độ tải trang, sự tương tác và tính ổn định của giao diện.  &lt;/p&gt;

&lt;p&gt;Việc tối ưu các chỉ số này trên trang web của bạn sẽ giúp cải thiện trải nghiệm người dùng và khả năng hiển thị trang web của bạn trên &lt;strong&gt;Google&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Các chỉ số trên &lt;strong&gt;Web Vitals&lt;/strong&gt; sẽ giúp các lập trình viên, đặc biệt là các lập trình viên frontend, đánh giá hiệu suất trang web của mình và đảm bảo rằng nó đáp ứng nhu cầu về tốc độ và trải nghiệm người dùng mượt mà.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lzhxd50zlk1ix2ceql9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lzhxd50zlk1ix2ceql9.png" alt="Image description" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Các chỉ số nào là quan trọng?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Định nghĩa&lt;/strong&gt;: Đây là chỉ số đo lường thời gian mà phần tử có nội dung lớn nhất trên trang web được tải và hiển thị cho người dùng. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mục tiêu&lt;/strong&gt;: Thời gian &lt;strong&gt;LCP&lt;/strong&gt; nên dưới &lt;strong&gt;2.5s&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Các cách làm giảm chỉ số LCP&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nén ảnh, nén video.&lt;/li&gt;
&lt;li&gt;Lazy loading cho các hình ảnh và tài nguyên không quan trọng.&lt;/li&gt;
&lt;li&gt;Tải các tài nguyên quan trọng (CSS, JS) ngay lập tức.&lt;/li&gt;
&lt;li&gt;Tránh các chuyển hướng trang không cần thiết.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;First Input Delay (FID)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Định nghĩa&lt;/strong&gt;: Đây là chỉ số đo lường độ trễ giữa việc người dùng lần đầu tiên tương tác (chẳng hạn như nhấp chuột hoặc ấn phím) và trang web phản hồi lại hành động đó.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mục tiêu&lt;/strong&gt;: Dưới &lt;strong&gt;100ms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Các cách làm giảm chỉ số FID&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chia nhỏ đoạn mã JS, tránh một hàm JS quá nặng làm chậm quá trình xử lý sự kiện.&lt;/li&gt;
&lt;li&gt;Sử dụng kỹ thuật &lt;strong&gt;defer&lt;/strong&gt; hoặc &lt;strong&gt;async&lt;/strong&gt; cho các script không quan trọng để làm giảm thời gian xử lý.&lt;/li&gt;
&lt;li&gt;Dùng &lt;strong&gt;Web Worker&lt;/strong&gt; và tách các tác vụ nặng ra khỏi luồng chính để không làm chậm phản hồi của trang.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Định nghĩa&lt;/strong&gt;: &lt;strong&gt;CLS&lt;/strong&gt; đo lường sự thay đổi vị trí các phần tử trên trang web trong quá trình tải. Nó phản ánh sự không ổn định bố cục của trang. Ví dụ khi người dùng nhấp chuột vào một phần tử và phần tử đó di chuyển đột ngột.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mục tiêu&lt;/strong&gt;: Điểm &lt;strong&gt;CLS&lt;/strong&gt; nên dưới &lt;strong&gt;0.1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Các cách tối ưu&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Đặt kích thước cho hình ảnh hoặc video.&lt;/li&gt;
&lt;li&gt;Áp dụng &lt;strong&gt;Skeleton Screens&lt;/strong&gt; (màn hình xương sống) để giảm sự thay đổi bố cục khi trang tải.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Đo các chỉ số trên như thế nào?
&lt;/h2&gt;

&lt;p&gt;Công cụ mình sử dụng chính để đo là &lt;strong&gt;DevTools&lt;/strong&gt; trên tab &lt;strong&gt;Performance&lt;/strong&gt; hoặc trên tab &lt;strong&gt;Lighthouse&lt;/strong&gt; trong Google Chrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tóm lại
&lt;/h2&gt;

&lt;p&gt;Các chỉ số &lt;strong&gt;Web Vitals&lt;/strong&gt; (LCP, FID, CLS) giúp bạn đánh giá chất lượng trải nghiệm người dùng và là yếu tố quan trọng trong &lt;strong&gt;SEO&lt;/strong&gt;. Để đảm bảo trang web của bạn không chỉ nhanh mà còn mang lại trải nghiệm mượt mà cho người dùng, bạn cần liên tục tối ưu hóa các chỉ số này. Việc cải thiện &lt;strong&gt;LCP&lt;/strong&gt;, &lt;strong&gt;FID&lt;/strong&gt; và &lt;strong&gt;CLS&lt;/strong&gt; sẽ giúp tăng cường khả năng tương tác của người dùng và nâng cao điểm số SEO của bạn, từ đó giúp website của bạn đạt hiệu suất tốt hơn và dễ dàng được Google xếp hạng cao hơn.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>performance</category>
    </item>
    <item>
      <title>Tối ưu Render Danh Sách 🚀</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Sat, 30 Nov 2024 13:57:08 +0000</pubDate>
      <link>https://dev.to/nddev_18/toi-uu-render-danh-sach-4cd4</link>
      <guid>https://dev.to/nddev_18/toi-uu-render-danh-sach-4cd4</guid>
      <description>&lt;p&gt;Chắc hẳn anh em làm frontend đã từng gặp rất nhiều bài toán render danh sách trong quá trình phát triển web. Đâu đó chúng ta có thể gặp trong các combo box, các scroll view, ... Nếu ít kinh nghiệm và xử lý thông thường, với một list data dài trung bình từ 2000 bản ghi, chúng ta sẽ phải mất 1s chờ đợi để cây DOM hiển thị đủ.&lt;/p&gt;

&lt;p&gt;Với xu hướng nâng cao trải nghiệm người dùng hiện tại, chúng ta không thể để một trang web khiến cho người dùng chờ đợi lâu đến như vậy được. Cho nên ngày hôm nay mình sẽ chia sẻ cho ae cách tối ưu hiệu năng và nâng cao trải nghiệm người dùng bằng những kỹ thuật mà mình biết nhé. Let’s go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bài toán: Xử lý Data có 10000 bản ghi danh sách nhân viên
&lt;/h2&gt;

&lt;p&gt;Mình sẽ chia các cách từ cơ bản đến phức tạp để giải bài toán trên như sau:&lt;/p&gt;

&lt;h3&gt;
  
  
  Kỹ thuật 1: Infinite Scroll
&lt;/h3&gt;

&lt;p&gt;Kỹ thuật đầu tiên mình biết khi học JS đó chính là &lt;strong&gt;Infinite Scroll&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Giải thích về kỹ thuật này&lt;/strong&gt;:&lt;br&gt;
Thay vì load toàn bộ danh sách 10000 bản ghi ra cùng lúc thì chúng ta có thể load danh sách bản ghi tầm 20 người. Trong đó, có 10 người sẽ ở vùng nhìn thấy, còn 10 người sẽ ở vùng không nhìn thấy. Khi người dùng cuộn chuột đến người thứ 18 thì tiếp tục load thêm 20 người nữa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ưu điểm&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kỹ thuật này sẽ làm tăng tốc độ tải trang.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nhược điểm&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cây DOM sau mỗi lần load sẽ ngày càng phình to dẫn đến quá tải.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64ycq9zi69hhj0340rec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64ycq9zi69hhj0340rec.png" alt="Image description" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Từ nhược điểm của phương pháp trên, chúng ta có thể nâng cao hơn một chút với kỹ thuật &lt;strong&gt;Virtual Scrolling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Giải thích về kỹ thuật này&lt;/strong&gt;:&lt;br&gt;
Lúc này, thay vì trực tiếp thêm 20 phần tử vào cây DOM mỗi khi loading data, chúng ta sẽ &lt;strong&gt;giới hạn số lượng phần tử hiển thị trên cây DOM là 20&lt;/strong&gt;. Khi người dùng cuộn, các phần tử ngoài vùng nhìn thấy sẽ bị loại bỏ và các phần tử mới sẽ được thêm vào, giúp giữ cho cây DOM luôn nhỏ gọn và hiệu quả.&lt;/p&gt;

&lt;p&gt;Mình biết đến kỹ thuật này khi bắt đầu học React.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Giải thích kỹ thuật Virtual Scrolling với thư viện &lt;code&gt;react-window&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
Chúng ta sẽ sử dụng một thư viện có tên là &lt;strong&gt;react-window&lt;/strong&gt; để triển khai virtual scrolling.&lt;/p&gt;

&lt;p&gt;Đọc đoạn code ví dụ dưới đây:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FixedSizeList&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-window&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Giả sử chúng ta có một danh sách dài 10.000 mục&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Item &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Hàm render mỗi item trong danh sách&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Sử dụng List component để render danh sách */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;        &lt;span class="c1"&gt;// Chiều cao của vùng hiển thị&lt;/span&gt;
        &lt;span class="na"&gt;itemCount&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// Số lượng phần tử trong danh sách&lt;/span&gt;
        &lt;span class="na"&gt;itemSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;        &lt;span class="c1"&gt;// Chiều cao của mỗi item&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;          &lt;span class="c1"&gt;// Chiều rộng của vùng hiển thị&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderRow&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;FixedSizeList&lt;/strong&gt;: Là một component trong thư viện &lt;code&gt;react-window&lt;/code&gt; giúp render các danh sách có chiều cao và chiều rộng cố định. Khi sử dụng &lt;code&gt;FixedSizeList&lt;/code&gt;, bạn không cần phải lo lắng về việc tính toán lại kích thước của các phần tử trong danh sách, vì các phần tử này có kích thước cố định.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;itemCount&lt;/strong&gt;: Xác định số lượng phần tử có trong danh sách. Đây là thuộc tính quan trọng để &lt;code&gt;react-window&lt;/code&gt; biết cần phải render bao nhiêu mục trong danh sách, mặc dù chỉ có một số lượng nhỏ mục được hiển thị tại một thời điểm.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;itemSize&lt;/strong&gt;: Chiều cao của mỗi item trong danh sách, tính bằng pixel (px). Điều này cần được chỉ định khi sử dụng &lt;code&gt;FixedSizeList&lt;/code&gt;, vì &lt;code&gt;react-window&lt;/code&gt; cần biết kích thước của từng mục để tính toán số lượng phần tử có thể hiển thị trong một khu vực nhất định.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;height và width&lt;/strong&gt;: Là kích thước của vùng hiển thị danh sách. Chỉ các phần tử nằm trong vùng này mới được render. Các phần tử bên ngoài vùng hiển thị sẽ không được render, giúp giảm tải cho bộ nhớ và tăng hiệu suất render.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;renderRow&lt;/strong&gt;: Là hàm để render ra các phần tử trong danh sách. Hàm này nhận vào đối tượng chứa &lt;code&gt;index&lt;/code&gt; (vị trí của phần tử trong danh sách) và &lt;code&gt;style&lt;/code&gt; (chứa các kiểu cần thiết để áp dụng cho phần tử, như vị trí, chiều cao, chiều rộng, v.v.). Hàm này chịu trách nhiệm hiển thị nội dung của mỗi mục trong danh sách.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kết quả sau khi chạy mặc dù danh sách có tận 10000 phần tử, tuy nhiên chỉ có khoảng từ 10 đến 20 phần tử được render tại thời điểm hiện tại tuỳ theo kích thước của vùng nhìn thấy. Khi chúng ta cuộn xuống thư viện sẽ xử lý thay thế các phần tử cho nhau một cách mượt mà, mà không làm chậm ứng dụng.&lt;/p&gt;

&lt;p&gt;Với những kỹ thuật như Infinite Scroll và Virtual Scrolling, chúng ta đã có thể giải quyết vấn đề hiệu suất khi render các danh sách dài, đặc biệt là với những ứng dụng web yêu cầu xử lý dữ liệu lớn. Nhờ việc chỉ render các phần tử cần thiết trong tầm nhìn, chúng ta không chỉ giảm thiểu tải cho trình duyệt mà còn nâng cao trải nghiệm người dùng với giao diện mượt mà, không bị giật lag.&lt;/p&gt;

&lt;p&gt;Tuy nhiên, mỗi kỹ thuật đều có ưu điểm và nhược điểm riêng, và việc lựa chọn giải pháp nào phù hợp còn tùy thuộc vào nhu cầu cụ thể của dự án. Nếu bạn cần một giải pháp nhanh chóng và đơn giản, Infinite Scroll có thể là lựa chọn tốt. Nhưng nếu bạn cần tối ưu hơn nữa với danh sách lớn, Virtual Scrolling là một bước tiến quan trọng. Chắc chắn, những kỹ thuật này sẽ giúp ứng dụng của bạn không chỉ hiệu quả hơn mà còn trở nên thân thiện với người dùng hơn.&lt;/p&gt;

&lt;p&gt;Chúc các bạn áp dụng thành công các kỹ thuật này trong các dự án của mình, và đừng quên thử nghiệm thêm các thư viện như react-window hoặc react-virtualized để cải thiện hơn nữa trải nghiệm người dùng!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>performance</category>
    </item>
    <item>
      <title>Tối ưu Frontend - Độ phức tạp của Style CSS ?🚀</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Sat, 30 Nov 2024 13:01:38 +0000</pubDate>
      <link>https://dev.to/nddev_18/toi-uu-frontend-do-phuc-tap-cua-style-css--2762</link>
      <guid>https://dev.to/nddev_18/toi-uu-frontend-do-phuc-tap-cua-style-css--2762</guid>
      <description>&lt;p&gt;Xin chào tất cả mọi người. Hôm nay mình sẽ chia sẻ cho mọi người một chủ đề rất là thú vị liên quan đến tối ưu hoá về độ phức tạp của STYLE. &lt;br&gt;
CSS là một ngôn ngữ lập trình quá quen thuộc với tất cả các lập trình viên web chúng ta, về cơ bản chúng ta đều có thể CSS thuần thục các layout không qua phức tạp. Tuy nhiên khi nói đến việc tối ưu hoá code giao diện, chúng ta lại thường bỏ qua CSS vì cho rằng chúng không ảnh hưởng nhiều đến hiệu năng.&lt;/p&gt;

&lt;p&gt;Cho đến tuần làm việc vừa rồi khi ngồi fix bug trên giao diện dự án Thần Số Học của công ty mình, mình mới thấy có cái bug là lặp CSS. Lúc này mình mới chợt nhớ ra là, à lâu quá rồi mình không còn thói quen kiểm tra lại render CSS vì toàn code thư viện bundle ăn sẵn. Đến khi cần phải code thuần HTML và CSS cho các task cụ thể thì mình lại bỏ quên và lãng phí đi kiến thức, kinh nghiệm và trải nghiệm của bản thân về tối ưu hoá cơ bản. &lt;/p&gt;

&lt;p&gt;Về cơ bản, nhiều anh em mới code sẽ chủ quan hoặc quên đi kiến thức về việc viết style. Chúng ta cần nhớ rằng có các trường hợp viết style làm ảnh hưởng đến hiệu năng như sau&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Style Inline Quá Nhiều
&lt;/h2&gt;

&lt;p&gt;Ảnh hưởng hiệu năng là do mỗi lần chuyển trang, trình duyệt không những phải render HTML mà còn phải render lại CSS. Thay vì thế, chúng ta nên để các style được load trong một file CSS duy nhất từ lần đầu để có thể tăng tốc độ load trang cho trình duyệt. Việc này vừa tối ưu hoá file HTML, vừa tận dụng được việc cache file tĩnh từ trình duyệt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hướng giải quyết&lt;/strong&gt;: Mình khuyên các bạn nên viết ra một file CSS riêng và hạn chế sử dụng inline CSS, vì inline CSS vừa khó maintain, vừa khó fix bug.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. CSS Không Tối Ưu và Quá Phức Tạp
&lt;/h2&gt;

&lt;p&gt;Việc viết CSS với nhiều cấp selector cũng ảnh hưởng đến hiệu năng load trang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Giải thích&lt;/strong&gt;: Ví dụ khi viết CSS, có những người sẽ viết kiểu này:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nf"&gt;#container&lt;/span&gt; &lt;span class="nc"&gt;.row&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="nc"&gt;.someClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Khi đó, trình duyệt sẽ phải load từ phải qua trái. Đầu tiên, nó sẽ tìm xem có bao nhiêu class tên là &lt;code&gt;someClass&lt;/code&gt;, sau đó lại phải tìm xem trong đống đó có bao nhiêu thẻ &lt;code&gt;p&lt;/code&gt;, rồi tiếp tục lại phải tìm xem số vừa tìm được có bao nhiêu thẻ có thẻ cha có class là &lt;code&gt;row&lt;/code&gt;. Nghe hết sức mệt mỏi đúng không? Việc đi loằng ngoằng selector như vậy dễ làm cho trình duyệt phải mất thời gian tìm và tính toán, dẫn đến việc render CSS lâu hơn và ảnh hưởng đến hiệu suất tải trang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hướng giải quyết&lt;/strong&gt;&lt;br&gt;
Người ta đã sinh ra một quy chuẩn đặt tên class gọi là &lt;strong&gt;BEM&lt;/strong&gt; (Block Element Modifier), thay vì phải chọc từ thằng cha tít tít ngoài vào, mục đích của BEM là giúp tránh bị trùng lặp CSS giữa các phần không mong muốn. Với quy tắc BEM, bạn có thể đặt tên class theo cách dễ hiểu và dễ quản lý mà không cần phải lo việc viết CSS phức tạp từ các thẻ ngoài vào.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ví dụ&lt;/strong&gt;: Giả sử bạn có hai list là &lt;code&gt;card&lt;/code&gt; và &lt;code&gt;phone&lt;/code&gt;, bên trong mỗi list lại có các item. Lúc này, bạn có thể đặt tên hai khối cha là &lt;code&gt;.card&lt;/code&gt; và &lt;code&gt;.phone&lt;/code&gt;, và các item bên trong mỗi khối sẽ được mang class riêng là &lt;code&gt;.card__item&lt;/code&gt; và &lt;code&gt;.phone__item&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Với cách đặt tên này, bạn có thể chọc thẳng vào tên class và viết CSS mà không cần phải lo việc đụng chạm giữa các item trong các list khác nhau nữa.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Font Import Quá Nhiều
&lt;/h2&gt;

&lt;p&gt;Chúng ta đều biết rằng một tệp font TTF thường khá cồng kềnh. Nếu một trang web có quá nhiều font và các font này tải chậm thì liệu text có hiển thị kịp không? Câu trả lời là &lt;strong&gt;không&lt;/strong&gt;, khi đó sẽ có một khoảng trắng trên trang web, điều này trông rất khó chịu và ảnh hưởng đến trải nghiệm người dùng.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&amp;amp;display=swap"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Roboto'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;font-display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c"&gt;/* Sử dụng swap cho font */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kinh nghiệm xử lý
&lt;/h3&gt;

&lt;p&gt;Cách mình xử lý vấn đề này là sử dụng thuộc tính &lt;code&gt;font-display: swap&lt;/code&gt;. Thông thường, các framework hiện nay đã tích hợp kỹ thuật này vào trong framework của họ. Giải thích đơn giản, kỹ thuật này có nghĩa là khi bạn đang load một font cần để hiển thị, text sẽ hiển thị dưới dạng một font khác (font mặc định đã được load từ trước) cho đến khi font chính được tải xong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Các vấn đề khác
&lt;/h3&gt;

&lt;p&gt;Ngoài vấn đề về font, còn một số trường hợp khác cần lưu ý như:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Không sử dụng file min (chưa tối ưu hoá CSS).&lt;/li&gt;
&lt;li&gt;Viết CSS bị lặp lại quá nhiều.&lt;/li&gt;
&lt;li&gt;Chồng chéo CSS do đặt trùng tên class.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kết Luận
&lt;/h3&gt;

&lt;p&gt;Như vậy, việc tối ưu hoá CSS không chỉ giúp cải thiện hiệu năng của trang web mà còn giúp bạn dễ dàng quản lý và bảo trì mã nguồn trong dự án. Dù là những thay đổi nhỏ, nhưng nếu được áp dụng đúng cách, chúng có thể mang lại những cải thiện đáng kể trong tốc độ tải trang và trải nghiệm người dùng.&lt;/p&gt;

&lt;p&gt;Hy vọng qua bài viết này, các bạn sẽ có thêm những kiến thức bổ ích để tối ưu hoá mã CSS trong các dự án của mình. Đừng quên chia sẻ những mẹo hay của bạn về việc tối ưu hoá CSS nhé!&lt;/p&gt;

&lt;p&gt;Chúc các bạn coding vui vẻ và hiệu quả! 😊&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>performance</category>
      <category>css</category>
    </item>
    <item>
      <title>Có thể bạn chưa biết (Phần 1)</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Fri, 08 Nov 2024 14:19:46 +0000</pubDate>
      <link>https://dev.to/nddev_18/co-the-ban-chua-biet-phan-1-3n2g</link>
      <guid>https://dev.to/nddev_18/co-the-ban-chua-biet-phan-1-3n2g</guid>
      <description>&lt;p&gt;Trong những năm tháng gần đây xu hướng của lập trình frontend thường nghiêng về phía lập trình viên ReactJS. Với sự ra đời cải tiến của NextJS 13, xu hướng này càng trở nên phổ biến hơn bao giờ hết. Với những tính năng mở rộng đặc biệt về SSR, SSG giúp tối ưu hoá SEO, hiệu suất và trải nghiệm người dùng. Một loạt những tính năng mới đó giúp các lập trình viên dễ dàng triển khai các ứng dụng web phức tạp với ít công sức hơn. &lt;/p&gt;

&lt;p&gt;Ngày tôi mới bước chân vào Framework này, tôi tự hỏi liệu nó có gì đặc biệt hơn ReactJS mà lại thu hút các lập trình viên chuyển đổi xu hướng đến vậy. Tôi bắt đầu mày mò tìm hiểu, nhiều người nói rằng NextJS khác gì ReactJS đâu, code ReactJS là code được NextJS mà, nhưng càng tìm hiểu sâu vào nó tôi càng nhận ra Next không chỉ là một Framework đơn giản để chạy trên ứng dụng React. &lt;/p&gt;

&lt;p&gt;Ngày hôm nay tôi viết bài viết này để chia sẻ cho mọi người thấy được những sự khác biệt đôi khi đến từ những điều rất đơn giản mà vô tình mọi người không để ý. &lt;/p&gt;

&lt;h2&gt;
  
  
  Phần 1 - Những thẻ đặc biệt trong NextJS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1 &lt;code&gt;&amp;lt;Head&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Thẻ &lt;code&gt;Head&lt;/code&gt; trong NextJS cho phép bạn chèn các metadata vào phần &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; của trang html, bao gồm tiêu đề, mô tả. liên kết đến các file CSS/JS và các thẻ metadata khác. Điều này rất hữu ích với SEO và trải nghiệm người dùng, đặc biệt trong các case điều chỉnh cụ thể cho từng trang.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/head&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My page title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Có thể bạn đã quá quen với việc sử dụng thẻ &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; để tạo liên kết nội bộ giữa các trang trong ứng dụng. Tuy nhiên, khi làm việc với &lt;strong&gt;NextJS&lt;/strong&gt;, bạn nên sử dụng thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;. Thẻ này có một điểm đặc biệt, được đội ngũ Next phát triển để tối ưu hóa tính năng &lt;strong&gt;client-side navigation&lt;/strong&gt;. Điều này giúp người dùng điều hướng nhanh chóng giữa các trang mà không cần tải lại toàn bộ trang.&lt;/p&gt;

&lt;p&gt;Khi bạn sử dụng thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; để liên kết đến trang B trong khi đang ở trang A, mặc định thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; sẽ sử dụng cơ chế &lt;strong&gt;prefetching&lt;/strong&gt;, tự động tải trước nội dung của trang B. Khi người dùng click vào liên kết, trang B đã gần như sẵn sàng để hiển thị. Tuy nhiên, cơ chế này cũng có những hạn chế đối với hiệu suất của trang web. &lt;/p&gt;

&lt;p&gt;Khi một trang có nhiều thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;, điều này có thể dẫn đến việc tải trước quá nhiều trang không cần thiết, gây ra hiệu ứng làm chậm tốc độ tải trang, ảnh hưởng đến trải nghiệm người dùng.&lt;/p&gt;

&lt;p&gt;May mắn thay, chúng ta có thể tùy chỉnh cơ chế &lt;strong&gt;prefetching&lt;/strong&gt; này một cách thủ công bằng cách sử dụng thuộc tính &lt;code&gt;prefetch={false}&lt;/code&gt; trong thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt; &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Go to About Page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ngoài ra, có một số tùy chọn rất hay mà bạn có thể sử dụng với thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; trong NextJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;scroll&lt;/strong&gt;: Tùy chọn này cho phép bạn quyết định liệu trang có tự động cuộn lên đầu khi người dùng điều hướng sang trang mới hay không. Điều này hữu ích khi bạn muốn giữ nguyên vị trí hiện tại của người dùng tại trang cũ, thay vì bắt đầu lại từ đầu trang mới.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;shallow&lt;/strong&gt;: Tùy chọn này giúp bạn điều hướng giữa các trang mà không cần tải lại dữ liệu hoặc làm mới hoàn toàn toàn bộ trang. Khi sử dụng &lt;code&gt;shallow={true}&lt;/code&gt;, NextJS chỉ thay đổi URL mà không làm ảnh hưởng đến toàn bộ UI của trang web. Điều này giúp cải thiện hiệu suất, đặc biệt trong các ứng dụng có trạng thái người dùng cần được giữ nguyên khi điều hướng giữa các trang.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ví dụ cụ thể về &lt;code&gt;shallow&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Lấy giá trị query từ URL&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPosts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Giả sử bạn gọi API hoặc tải dữ liệu bài viết theo danh mục&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Fetching posts for category: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// Gọi API để lấy các bài viết theo danh mục&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/posts?category=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Chạy lại khi 'category' thay đổi&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blog - &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;No posts available.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Giải thích về cách hoạt động trong ví dụ trên
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Cập nhật URL mà không reload trang:
&lt;/h4&gt;

&lt;p&gt;Khi người dùng nhấp vào "Tech" hoặc "Design" trong thành phần &lt;code&gt;MyComponent&lt;/code&gt;, URL sẽ thay đổi thành &lt;code&gt;/blog?category=tech&lt;/code&gt; hoặc &lt;code&gt;/blog?category=design&lt;/code&gt;. Tuy nhiên, vì chúng ta sử dụng tùy chọn &lt;code&gt;shallow={true}&lt;/code&gt; trong thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;, trang &lt;strong&gt;không bị tải lại&lt;/strong&gt;, chỉ có URL trong thanh địa chỉ thay đổi.&lt;/p&gt;

&lt;p&gt;Điều này có nghĩa là NextJS sẽ &lt;strong&gt;cập nhật URL mà không reload lại toàn bộ trang&lt;/strong&gt;. Mặc dù URL thay đổi và có thể người dùng đang ở một "trang" khác, nhưng trang hiện tại vẫn giữ nguyên mà không phải tải lại từ đầu. Điều này giúp cải thiện hiệu suất và mang lại trải nghiệm người dùng mượt mà hơn.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cập nhật nội dung theo danh mục:
&lt;/h4&gt;

&lt;p&gt;Trong ví dụ trên, chúng ta sử dụng &lt;code&gt;useEffect&lt;/code&gt; để theo dõi sự thay đổi của &lt;code&gt;category&lt;/code&gt; trong URL, giá trị của &lt;code&gt;category&lt;/code&gt; được lấy thông qua &lt;code&gt;router.query&lt;/code&gt; từ NextJS Router.&lt;/p&gt;

&lt;p&gt;Khi URL thay đổi, cụ thể là khi &lt;code&gt;category&lt;/code&gt; thay đổi (ví dụ: từ &lt;code&gt;tech&lt;/code&gt; sang &lt;code&gt;design&lt;/code&gt;), &lt;code&gt;useEffect&lt;/code&gt; sẽ &lt;strong&gt;gọi lại API&lt;/strong&gt; để tải lại dữ liệu mới theo danh mục hiện tại. API sẽ trả về danh sách các bài viết liên quan đến danh mục đó, và chúng ta sẽ cập nhật state &lt;code&gt;posts&lt;/code&gt; với các bài viết mới.&lt;/p&gt;

&lt;p&gt;Điều này có nghĩa là &lt;strong&gt;nội dung của trang sẽ được cập nhật mà không cần phải tải lại toàn bộ trang&lt;/strong&gt;. Các bài viết sẽ được tải và hiển thị lại chỉ với phần dữ liệu mới mà không làm tải lại toàn bộ giao diện trang. Điều này mang lại hiệu suất tối ưu và cải thiện trải nghiệm người dùng, vì người dùng không phải chờ đợi trang tải lại hoàn toàn mỗi khi điều hướng giữa các danh mục.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tóm tắt:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cập nhật URL mà không reload trang&lt;/strong&gt;: Với &lt;code&gt;shallow={true}&lt;/code&gt;, NextJS thay đổi URL trong thanh địa chỉ mà không tải lại toàn bộ trang.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cập nhật nội dung theo danh mục&lt;/strong&gt;: &lt;code&gt;useEffect&lt;/code&gt; theo dõi sự thay đổi của &lt;code&gt;category&lt;/code&gt; trong URL, gọi lại API và cập nhật dữ liệu mới mà không làm reload trang.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;locale&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tùy chọn &lt;code&gt;locale&lt;/code&gt; trong thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; cho phép bạn chỉ định một &lt;strong&gt;locale cụ thể&lt;/strong&gt; cho liên kết. Điều này cực kỳ hữu ích khi bạn phát triển một ứng dụng đa ngôn ngữ và muốn cho phép người dùng điều hướng đến các phiên bản ngôn ngữ khác nhau của cùng một trang.&lt;/p&gt;

&lt;p&gt;Khi bạn có một ứng dụng NextJS hỗ trợ nhiều ngôn ngữ, bạn có thể sử dụng thuộc tính &lt;code&gt;locale&lt;/code&gt; để điều hướng đến phiên bản ngôn ngữ tương ứng của trang hiện tại. Ví dụ, bạn có thể tạo một liên kết đến trang "About" nhưng với ngôn ngữ khác, như tiếng Pháp hoặc tiếng Tây Ban Nha, thay vì tiếng Anh mặc định.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ví dụ:
&lt;/h3&gt;

&lt;p&gt;Giả sử bạn có một trang "About" và muốn tạo một liên kết dẫn đến phiên bản tiếng Pháp của trang này, bạn có thể sử dụng &lt;code&gt;locale="fr"&lt;/code&gt; trong thẻ &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; như sau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt; &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fr"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Go to About Page (French)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Thẻ &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt; trong Next.js được thiết kế để tối ưu hóa việc hiển thị hình ảnh. Thay vì sử dụng thẻ &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; thông thường, bạn có thể sử dụng &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt; để Next.js tự động xử lý việc tải ảnh một cách thông minh, giảm thiểu dung lượng tải về, tối ưu hóa kích thước hình ảnh theo từng thiết bị, và hỗ trợ lazy loading.&lt;br&gt;&lt;br&gt;
Next JS hỗ trợ cache ảnh rất thông minh. Khi ảnh của bạn được yêu cầu lần đầu tiên, nó sẽ load ảnh và lưu vào bộ nhớ cache, vì vậy các lần yêu cầu tải ảnh tiếp theo sẽ nhanh hơn rất nhiều.&lt;/p&gt;

&lt;p&gt;Ví dụ ảnh của mình trong public có tên là:&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0grsriww6rdpzfhz03n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0grsriww6rdpzfhz03n.png" alt="Image description" width="208" height="36"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Tuy nhiên, sau khi được load thì nó sẽ có thêm một cái đuôi:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flvgdih3aa8f1cvrtjzdd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flvgdih3aa8f1cvrtjzdd.png" alt="Image description" width="800" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Đuôi &lt;code&gt;c1575e8a&lt;/code&gt; là một mã hash được sinh ra khi Next.js tối ưu hóa ảnh (hoặc các tài nguyên tĩnh khác như CSS, JS). Mã hash này là duy nhất cho mỗi ảnh và thay đổi nếu ảnh thay đổi.&lt;/li&gt;
&lt;li&gt;Mã hash này giúp ngăn ngừa vấn đề cache cũ trong trình duyệt: nếu ảnh thay đổi (ví dụ: bạn cập nhật hoặc thay đổi ảnh), mã hash sẽ thay đổi và trình duyệt sẽ tải lại ảnh mới thay vì sử dụng ảnh cũ từ bộ nhớ cache.&lt;/li&gt;
&lt;li&gt;Thư mục &lt;code&gt;/_next/static/&lt;/code&gt; là nơi Next.js lưu trữ các tệp static sau khi chúng đã được tối ưu hóa. Khi bạn sử dụng Next.js để tối ưu hóa hình ảnh, ảnh đó sẽ được di chuyển vào thư mục này sau khi được xử lý.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ngoài ra còn có một số props hay dùng:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;priority&lt;/strong&gt;: Đánh dấu ảnh là ưu tiên tải trước các ảnh khác. Cái này có thể ảnh hưởng đến việc cache, vì Next.js sẽ chắc chắn tải ảnh đó đầu tiên.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;quality&lt;/strong&gt;: Đặt chất lượng ảnh từ 1-100. Giá trị mặc định là 75, và bạn có thể giảm chất lượng để tiết kiệm băng thông, nhưng vẫn giữ ảnh ở độ phân giải đủ tốt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;placeholder&lt;/strong&gt; và &lt;strong&gt;blurDataURL&lt;/strong&gt;: Những tính năng này giúp tạo hiệu ứng placeholder khi ảnh chưa được tải hoàn toàn. Tuy nhiên, ảnh thực tế sẽ được cache và tải nhanh hơn sau khi đã được tối ưu. Lưu ý thuộc tính này chỉ áp dụng được với những ảnh có đuôi &lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.png&lt;/code&gt;, hoặc &lt;code&gt;.webp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fill&lt;/strong&gt;: Khi sử dụng &lt;code&gt;fill={true}&lt;/code&gt;, Next.js sẽ tự động tính toán kích thước ảnh dựa trên không gian có sẵn và làm cho ảnh phù hợp với bố cục. Điều này vẫn hoạt động với tính năng cache ảnh của Next.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unoptimized&lt;/strong&gt;: Trong Next.js, thuộc tính &lt;code&gt;unoptimized&lt;/code&gt; không phải là một thuộc tính bắt buộc trong mọi trường hợp, và bạn không phải lúc nào cũng cần phải thêm nó vào thẻ &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt;. Tuy nhiên, có một số trường hợp mà bạn có thể cần phải sử dụng &lt;code&gt;unoptimized={true}&lt;/code&gt; hoặc có thể gặp phải yêu cầu thêm thuộc tính này khi tải ảnh.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hai thẻ cuối này thì ít dùng hơn nhưng mình cũng thấy nó đặc biệt nên thêm vào&lt;/p&gt;


&lt;h3&gt;
  
  
  4. &lt;code&gt;&amp;lt;Script&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Thẻ &lt;code&gt;&amp;lt;Script&amp;gt;&lt;/code&gt; không chỉ giúp bạn chèn các script vào trang mà còn hỗ trợ tối ưu hóa tải và thực thi các script bên ngoài. Điều này giúp bạn kiểm soát tốt hơn việc tải tài nguyên bên ngoài, giảm thiểu thời gian chờ đợi và cải thiện hiệu suất tổng thể.&lt;/p&gt;


&lt;h3&gt;
  
  
  5. &lt;code&gt;&amp;lt;ErrorBoundary&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Bạn có thể sử dụng một Error Boundary trong React để bắt lỗi JavaScript trong ứng dụng của bạn và hiển thị một giao diện thay thế hoặc thông báo lỗi cho người dùng khi xảy ra sự cố.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getDerivedStateFromError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Cập nhật state để render giao diện lỗi thay vì giao diện bình thường&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Ghi lại lỗi vào một dịch vụ log lỗi (như Sentry, LogRocket, v.v.)&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error caught:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Bạn có thể render bất kỳ giao diện thay thế nào khi gặp lỗi&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Something went wrong.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;whiteSpace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pre-wrap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorInfo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentStack&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ErrorBoundary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Như vậy tôi vừa giới thiệu cho bạn những thẻ đặc biệt trong NextJS mà tôi đã tìm hiểu. Hi vọng bài viết sẽ bổ sung cho bạn thêm kiến thức về lập trình. Mong rằng những phần tiếp theo sẽ vẫn được các bạn ủng hộ, chúng ta sẽ cùng nhau khám phá thêm những điều mới mẻ hơn nữa. Hẹn gặp lại&lt;/p&gt;

</description>
    </item>
    <item>
      <title>NEXTJS-15 BREAKING CHANGE</title>
      <dc:creator>Phúc Nguyễn</dc:creator>
      <pubDate>Sun, 27 Oct 2024 18:24:03 +0000</pubDate>
      <link>https://dev.to/nddev_18/nextjs-15-breaking-change-2nkd</link>
      <guid>https://dev.to/nddev_18/nextjs-15-breaking-change-2nkd</guid>
      <description>&lt;h1&gt;
  
  
  NextJS Version 15 Chính Thức Phát Hành
&lt;/h1&gt;

&lt;p&gt;Vào &lt;strong&gt;Thứ Hai ngày 21 tháng 10 năm 2024&lt;/strong&gt;, sau rất nhiều phiên bản RC được phát hành trước đó, &lt;strong&gt;NextJS&lt;/strong&gt; chính thức cho phát hành &lt;strong&gt;phiên bản version 15&lt;/strong&gt; của mình.&lt;br&gt;&lt;br&gt;
Không có gì bất ngờ khi những thay đổi được đưa ra tại các phiên bản thử nghiệm trước đó được phát triển trong version mới này của NextJS. Bài viết này là quan điểm của mình về những thay đổi mà mình cảm thấy đáng chú ý.&lt;/p&gt;

&lt;p&gt;Trước tiên hãy cùng dạo qua một vòng những thay đổi trong phiên bản lần này. Mình sẽ tóm tắt lại thành các ý chính, còn cụ thể hơn chúng ta có thể vào trang chủ của Vercel để tìm kiếm thông tin chi tiết hơn.&lt;br&gt;&lt;br&gt;
&lt;a href="https://nextjs.org/blog/next-15" rel="noopener noreferrer"&gt;NextJS Blog - Next 15&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Như đã hứa trước đó, team phát triển NextJS mỗi năm đều tung ra một lần upgrade version lớn và trong lần gần nhất, họ có nói về một công cụ mới sẽ xuất hiện và thay thế Webpack. Và trong lần release này, nó đã được chính thức đưa vào hoạt động với cam kết tốc độ build nhanh hơn phiên bản trước rất nhiều lần.&lt;/p&gt;

&lt;h2&gt;
  
  
  TurboPack
&lt;/h2&gt;

&lt;p&gt;Trong phiên bản 15 của Next.js, công cụ &lt;strong&gt;TurboPack&lt;/strong&gt; được giới thiệu với tốc độ đáng kinh ngạc so với các phiên bản trước. TurboPack được thiết kế nhằm tối ưu hóa thời gian build và phát triển ứng dụng với khả năng xử lý nhanh gấp nhiều lần so với &lt;strong&gt;Webpack&lt;/strong&gt;, vốn là công cụ phổ biến trước đây.&lt;/p&gt;

&lt;p&gt;Theo các thử nghiệm do nhóm phát triển Vercel công bố, TurboPack có thể tăng tốc độ build gấp &lt;strong&gt;700 lần&lt;/strong&gt; so với Webpack trong các dự án lớn, nhờ khả năng tận dụng tối đa tài nguyên phần cứng và kiến trúc mới. So với các phiên bản cũ, sự cải tiến này giúp tăng hiệu suất build, giảm thời gian chờ đợi khi thực hiện thay đổi mã nguồn, từ đó cải thiện trải nghiệm cho các anh mắt thâm =)).&lt;/p&gt;

&lt;p&gt;Khi khởi tạo dự án mới NextJS 15, đội ngũ phát triển cũng đã tự động thêm &lt;strong&gt;flag --turbopack&lt;/strong&gt; vào script trên môi trường dev cho chúng ta tại file &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ve6rhma3xtu9m1j272n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ve6rhma3xtu9m1j272n.png" alt="TurboPack" width="393" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;Thay đổi thứ hai đó chính là về &lt;strong&gt;dependencies&lt;/strong&gt;. Chúng ta có thể thấy &lt;strong&gt;version mới nhất của React (v.19)&lt;/strong&gt; tại file &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpqfpmn3o1zk3vtl2xaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpqfpmn3o1zk3vtl2xaa.png" alt="React Version" width="536" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hiện tại, React vẫn chưa đưa ra version 19 chính thức, tuy nhiên &lt;strong&gt;version RC&lt;/strong&gt; cũng là version ổn định để test thử trên product một cách ngon lành :3. Nhưng mà lỗi thì chưa có ai support đâu hehe :]&lt;/p&gt;




&lt;h2&gt;
  
  
  Hook Xử Lý Form
&lt;/h2&gt;

&lt;p&gt;Mặc dù các hook xử lý form được React đưa ra thử nghiệm như &lt;code&gt;useActionState&lt;/code&gt;, &lt;code&gt;useFormStatus&lt;/code&gt;, ... tuy nhiên đã được NextJs đem vào chính thức. Các bạn có thể search các keyword trên để tìm đọc thêm. Cá nhân mình thì không ấn tượng về những thằng này lắm vì &lt;code&gt;react-hook-form&lt;/code&gt; đã hỗ trợ mình tất cả những case này rất là lâu rồi. Sau này nếu có cần optimize code, giảm bớt thư viện bên ngoài lại thì có lẽ mình sẽ cần sau.&lt;/p&gt;

&lt;h2&gt;
  
  
  React-Compiler
&lt;/h2&gt;

&lt;p&gt;Một thay đổi khác là về &lt;strong&gt;react-compiler&lt;/strong&gt;. Trên version 15 này, chúng ta có thể sử dụng thử nghiệm react-compiler cho dự án của mình. Để sử dụng cụ thể, các bạn có thể cài theo các bước. Mình sẽ để đường link hướng dẫn cụ thể tại đây và các bạn có thể làm theo:&lt;br&gt;&lt;br&gt;
&lt;a href="https://nextjs.org/docs/app/api-reference/next-config-js/reactCompiler" rel="noopener noreferrer"&gt;NextJS Docs - React Compiler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cá nhân mình thấy react-compiler khá tiện. Nó giúp mình không cần phải đau đầu về các case sử dụng &lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, &lt;code&gt;ReactMemo&lt;/code&gt;. Công việc tối ưu này sẽ được giao lại cho React, nó sẽ tự nhận biết khi nào cần rerender lại để tránh các lần lặp mất kiểm soát. Tuy nhiên, chúng ta vẫn cần phải chờ thông báo hỗ trợ chính thức từ NextJS trước khi quyết định đưa vào production nha =)). Tránh nghịch dại đưa vào rồi méo biết chỗ nào mà sửa vì nó mới chỉ thử nghiệm thôi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Change: Chuyển Các Dynamic Function Thành Async Function
&lt;/h2&gt;

&lt;p&gt;Các function dưới đây là cái mình hay sử dụng. Nó cần được chuyển thành &lt;strong&gt;async function&lt;/strong&gt; và sử dụng &lt;strong&gt;await&lt;/strong&gt;. Ngoài ra có một số cái khác nữa nhưng mình ít dùng đến:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cookies&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;headers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;params&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;searchParams&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trước đây, chúng ta import thẳng các thư viện hỗ trợ kèm theo vào function component và gọi trực tiếp ra dùng. Tuy nhiên, lần này chúng ta phải chuyển function component thành async function và sử dụng await để có thể gọi hàm hoặc có thể sử dụng một hook mới có tên là &lt;code&gt;use&lt;/code&gt; (đang được thử nghiệm).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7852qyc3qpnopiy2eud1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7852qyc3qpnopiy2eud1.png" alt="Image description" width="506" height="815"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxe6ztx82ejpceg1zmed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxe6ztx82ejpceg1zmed.png" alt="Image description" width="505" height="545"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Caching
&lt;/h2&gt;

&lt;p&gt;Tiếp tục, thêm một thay đổi mà có lẽ là mình cùng các anh em dev frontend thích nhất trong version lần này đó là về phần &lt;strong&gt;CACHE&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching của Fetch
&lt;/h3&gt;

&lt;p&gt;NextJS chính thức bỏ &lt;strong&gt;cache mặc định&lt;/strong&gt;. Nếu bây giờ chúng ta muốn cache khi gọi API thì phải cần thêm flag &lt;code&gt;cache: "force-cache"&lt;/code&gt; vào trong tùy chọn của fetch. Trước kia mình đã nhiều lần khó chịu khi xử lý các case cache mặc định và thường tắt luôn để tránh bực mình, sau đó chuyển sang dùng thư viện như tanstack-query vô cùng xịn xò.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching của Route Handler
&lt;/h3&gt;

&lt;p&gt;Khi &lt;strong&gt;fetch method GET&lt;/strong&gt; được gọi, chúng ta sẽ không cần phải lo về việc nó chỉ được gọi một lần đầu tiên dẫn đến kết quả trả về không như mong muốn trong các lần cập nhật tiếp theo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-side Router Caching
&lt;/h3&gt;

&lt;p&gt;Trước kia khi bắn API thêm sửa một cái gì đó trên trang, mình có dùng &lt;code&gt;router.push&lt;/code&gt; để chuyển hướng đến trang kết quả hoặc dùng thẻ Link. Tuy nhiên, mình không tìm thấy sản phẩm thêm mới đó nếu không gọi thêm &lt;code&gt;router.refresh&lt;/code&gt;. Lý do chính là &lt;strong&gt;NextJS mặc định cache&lt;/strong&gt; những trang tĩnh đã được build xong. Ở version lần này mình sẽ không cần phải làm vậy nữa, &lt;strong&gt;mặc định cache đã được gỡ bỏ&lt;/strong&gt; rồi. Tuyệt vời luôn =)).&lt;/p&gt;




&lt;h2&gt;
  
  
  Tính Năng Mới: PPR (Partial Page Rendering)
&lt;/h2&gt;

&lt;p&gt;Một tính năng thử nghiệm đáng chú ý khác trong NextJS 15 là &lt;strong&gt;PPR (Partial Page Rendering)&lt;/strong&gt;, giúp cải thiện hiệu suất tải trang bằng cách chỉ render một phần của trang thay vì toàn bộ. Thay vì reload toàn bộ các components trên một trang khi có sự thay đổi, PPR chỉ re-render các thành phần bị tác động, giúp tiết kiệm tài nguyên và giảm thiểu thời gian phản hồi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cách Hoạt Động của PPR
&lt;/h3&gt;

&lt;p&gt;Với PPR, các phần trang được chia thành các phần nhỏ hơn, có thể cập nhật một cách độc lập dựa trên những thay đổi nhỏ mà không làm ảnh hưởng đến các thành phần khác trên cùng một trang. Điều này đặc biệt hữu ích cho các ứng dụng có nhiều thành phần tương tác, giúp tăng tốc độ phản hồi và nâng cao trải nghiệm người dùng.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ưu Điểm của PPR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tối ưu hóa tài nguyên&lt;/strong&gt;: Giảm thiểu số lượng mã cần render lại, tránh render không cần thiết.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cải thiện hiệu suất&lt;/strong&gt;: Giảm thời gian tải trang khi có thay đổi nhỏ, đặc biệt hữu ích cho các ứng dụng có nhiều dữ liệu động.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tương thích với các tính năng NextJS khác&lt;/strong&gt;: PPR có thể kết hợp với các tính năng như &lt;code&gt;getServerSideProps&lt;/code&gt; hoặc &lt;code&gt;getStaticProps&lt;/code&gt;, giúp chúng ta xây dựng các ứng dụng mạnh mẽ và hiệu suất cao hơn.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lưu Ý Khi Sử Dụng PPR
&lt;/h3&gt;

&lt;p&gt;Vì tính năng PPR hiện đang trong giai đoạn thử nghiệm, NextJS khuyến cáo chỉ nên sử dụng nó trong môi trường phát triển hoặc thử nghiệm. Trước khi đưa vào production, hãy đảm bảo rằng PPR hoạt động ổn định và tương thích với toàn bộ ứng dụng của bạn.&lt;/p&gt;

&lt;p&gt;Để kích hoạt PPR trong dự án của bạn, hãy tham khảo hướng dẫn chi tiết trên trang tài liệu chính thức của NextJS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Một Số Thay Đổi Nhỏ Khác
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Route Indicator&lt;/strong&gt;: Có icon nhỏ dưới màn hình môi trường dev để dễ nhận biết router static và dynamic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharp&lt;/strong&gt;: Không cần phải run install để optimize nữa, tự động cài sẵn trong project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;next.config.ts&lt;/strong&gt;: Cuối cùng thì cái chữ &lt;code&gt;j&lt;/code&gt; nó cũng thành chữ &lt;code&gt;t&lt;/code&gt; rồi, chắc là chơi thân với TypeScript hơn rồi đấy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint 9 Support&lt;/strong&gt;: Hỗ trợ version 9 rồi nha, không biết có đấm nhau với prettier nữa không chứ mấy lần setup là hơi mệt =)).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ý Kiến Của Mình
&lt;/h2&gt;

&lt;p&gt;Kết thúc lại bài viết, mình sẽ nêu lên ý kiến riêng của cá nhân mình về lần cập nhật này.&lt;br&gt;
Phiên bản lần này mình ấn tượng nhất là phần cache, ngoài ra nó cũng không có gì làm mình phải đáng lo sợ. Mình nghĩ, mình cũng như các lập trình viên frontend khác ngoài kia, đều có thể tiếp tục sử dụng nextjs14 một cách bình thường mà không nhất thiết cần phải lên ngay nextjs15 bởi có lẽ reactjs 19 vẫn chưa ra mắt hoàn toàn. Cũng không cần phải quá vội vàng update dự án vì vercel cũng có công cụ &lt;code&gt;@next/codemode&lt;/code&gt; giúp chúng ta nâng cấp dự án một cách vô cùng dễ dàng. Chúng ta đều có thể chờ cho đến khi version mới nhất của react ra mắt chính thức để có thể yên tâm chạy trên production. &lt;br&gt;
Ok, hi vọng rằng bài viết của mình có thể tóm tắt được thay cho mấy chục trang docs cập nhật của nextjs. Cảm ơn bạn đã đọc bài viết, chúc bạn một ngày tốt lành.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
