<?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>Forem: mikebui</title>
    <description>The latest articles on Forem by mikebui (@buiminh15).</description>
    <link>https://forem.com/buiminh15</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%2F626927%2F10d5e939-2d8f-4d74-a155-681d32919de3.png</url>
      <title>Forem: mikebui</title>
      <link>https://forem.com/buiminh15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/buiminh15"/>
    <language>en</language>
    <item>
      <title>Dùng Profile để kiểm tra hiệu suất của React App</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Tue, 24 May 2022 01:37:02 +0000</pubDate>
      <link>https://forem.com/buiminh15/dung-profile-de-kiem-tra-hieu-suat-cua-react-app-13lg</link>
      <guid>https://forem.com/buiminh15/dung-profile-de-kiem-tra-hieu-suat-cua-react-app-13lg</guid>
      <description>&lt;p&gt;Bài viết được dịch từ:&lt;br&gt;
&lt;a href="https://kentcdodds.com/blog/profile-a-react-app-for-performance"&gt;https://kentcdodds.com/blog/profile-a-react-app-for-performance&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thực hành dựa trên &lt;a href="https://github.com/kentcdodds/bookshelf"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cài đặt Extension
&lt;/h3&gt;

&lt;p&gt;Cần cài &lt;strong&gt;React DevTools extension&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Khởi động app
&lt;/h3&gt;

&lt;p&gt;Ứng dụng bookshelf sử dụng  &lt;code&gt;react-scripts&lt;/code&gt; (nhờ &lt;code&gt;create-react-app&lt;/code&gt;), vì vậy sau khi bạn đã cài đặt dự án ở máy mình, hãy chạy &lt;code&gt;npm run start&lt;/code&gt; để chạy server. Thao tác này sẽ hiển thị ứng dụng trong trình duyệt của bạn tại &lt;code&gt;http://localhost: 3000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dkdDdtPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4u66q0xs7xe53dmfvqj3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dkdDdtPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4u66q0xs7xe53dmfvqj3.PNG" alt="Image anh 1" width="766" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Profiler
&lt;/h3&gt;

&lt;p&gt;F12 trên browser chọn tab &lt;strong&gt;Profiler&lt;/strong&gt;. Bây giờ bạn có thể ấn vào vòng tròn nhỏ màu xanh lam để &lt;strong&gt;"Start profiling"&lt;/strong&gt; ứng dụng.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LVAAQfUR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/px5bwkt9s29385ratn7y.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LVAAQfUR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/px5bwkt9s29385ratn7y.PNG" alt="Image anh 2" width="770" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Từ đây, hãy tiếp tục và tương tác với ứng dụng một chút. Tôi sẽ đăng ký một tài khoản mới. Sau đó ấn vào vòng tròn nhỏ màu đỏ để &lt;strong&gt;"Stop profiling."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--omvftIBI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76ualpfzdzq1f1k0c6gf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--omvftIBI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76ualpfzdzq1f1k0c6gf.PNG" alt="Image anh 3" width="765" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Khám phá dữ liệu hồ sơ
&lt;/h3&gt;

&lt;p&gt;Từ đây, bạn có một số tùy chọn để khám phá dữ liệu mà DevTools đã thu thập khi bạn tương tác với ứng dụng. Chế độ xem mặc định là "Flamegraph chart" và cũng có "Ranked chart". Đây là "Flamegraph chart" trông như thế nào (nếu bạn muốn xem "Ranked chart", bạn sẽ phải tự mình làm điều này 😜):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a7eSE0XT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/669hx36iii9a4fi2i0vf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a7eSE0XT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/669hx36iii9a4fi2i0vf.PNG" alt="Image anh 4" width="763" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chúng ta có thể đi sâu vào phân tích nội dung này trong một bài đăng khác.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cạm bẫy: đo lường ở chế độ phát triển
&lt;/h3&gt;

&lt;p&gt;Tôi muốn chỉ ra một cạm bẫy nghiêm trọng mà bạn cần tránh khi thực hiện các phép đo hiệu suất như lập hồ sơ (Profiling). Hiện tại, chúng ta đang đo lường hiệu quả hoạt động của ứng dụng trong chế độ phát triển. Nếu bạn đã sử dụng React được một thời gian, bạn  biết rõ rằng nó có rất nhiều cảnh báo ở môi trường phát triển để giúp bạn tránh khỏi các vấn đề do code sai lý thuyết. Đây là một trong những điều tôi yêu thích nhất ở React, nhưng điều đó đi kèm với chi phí hiệu suất (thường là đáng kể).&lt;/p&gt;

&lt;p&gt;Do đó, các phép đo hiệu suất của bạn bị nhiễm bẩn bởi môi trường phát triển của React.&lt;/p&gt;

&lt;p&gt;Vì vậy, nếu bạn muốn có được phép đo chính xác về hiệu suất của ứng dụng trên môi trường production, bạn nên đảm bảo thực hiện các phép đo trên môi trường production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build và đo trên môi trường production
&lt;/h3&gt;

&lt;p&gt;Vì vậy, hãy chạy &lt;code&gt;npm run build&lt;/code&gt;. Tiếp theo, chạy &lt;code&gt;npx serve -s build&lt;/code&gt; để chạy trên server. Vào port 5000 và chạy profiler. Nhưng không?!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FdBq8zpy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y01pa5uxil5ovhjca8yy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FdBq8zpy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y01pa5uxil5ovhjca8yy.PNG" alt="Image 5" width="795" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Profiling not supported.&lt;br&gt;
Profiling support requires either a development or production-profiling build of React v16.5+.&lt;br&gt;
Learn more at fb.me/react-profiling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hóa ra, React có code dành riêng cho việc lập hồ sơ và vì lợi ích của việc làm cho ứng dụng của bạn nhanh nhất có thể, họ đã xóa code đó khỏi môi trường production.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LƯU Ý: Nếu bạn đang sử dụng &lt;code&gt;create-react-app&lt;/code&gt; với &lt;code&gt;react-scripts @&amp;gt; = 3.2.0&lt;/code&gt; thì bạn có thể chỉ cần chạy &lt;code&gt;npx react-scripts build --profile&lt;/code&gt; và nó sẽ thực hiện tất cả những việc này cho bạn (nhờ Jacob) và bạn có thể bỏ qua cạm bẫy tiếp theo. Nếu không, vui lòng đọc tiếp.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Cập nhật cấu hình webpack để tạo hồ sơ trên môi trường production
&lt;/h3&gt;

&lt;p&gt;Như lưu ý trên, ở môi trường production loại bỏ hầu hết các code hữu ích ở môi trường phát triển, nhưng vẫn giữ nguyên đoạn code lập hồ sơ. Nó vẫn chậm hơn một chút, nhưng nó cho chúng ta ý tưởng  về cách các component của chúng ta đang hoạt động trong môi trường production.&lt;/p&gt;

&lt;p&gt;Có một số cách để giải quyết vấn đề này, nhưng đơn giản nhất là &lt;strong&gt;cập nhật cấu hình webpack thành alias&lt;/strong&gt; bất kỳ import nào của các mô-đun nhất định vào phiên bản lập hồ sơ của mô-đun đó. Có hai mô-đun như vậy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;react-dom&lt;/code&gt; -&amp;gt; &lt;code&gt;react-dom/profiling&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scheduler/tracing -&amp;gt;&lt;/code&gt;scheduler/tracing-profiling`&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cả hai đều là các package React và cần đoạn code đặc biệt để việc lập hồ sơ hoạt động.&lt;/p&gt;

&lt;p&gt;Cách bạn cập nhật cấu hình webpack sẽ khác nhau dựa trên framework bạn đang sử dụng (create-react-app, next.js, gatsby.js hoặc của riêng bạn với webpack tự xây). Trong trường hợp này, chúng tôi đang sử dụng &lt;strong&gt;create-react-app&lt;/strong&gt; và không có cách nào được hỗ trợ chính thức để mở rộng hoặc sửa đổi cấu hình &lt;strong&gt;webpack&lt;/strong&gt;.&lt;br&gt;
Vì đang test ở local nên chúng ta có thể sửa trong &lt;strong&gt;node_modules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vì vậy, nếu bạn đang sử dụng &lt;strong&gt;&lt;a href="mailto:react-scripts@3.1.1"&gt;react-scripts@3.1.1&lt;/a&gt;&lt;/strong&gt; (hoặc ở đâu đó xung quanh đó), thì bạn có thể mở cấu hình webpack tại đây: &lt;strong&gt;./node_modules/react-scripts/config/webpack.config.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sau đó xác định vị trí code trông giống như thế này và thêm các dòng ghi chú:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yqt1IMJU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cq3xzebsaymeo4dwn4cy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yqt1IMJU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cq3xzebsaymeo4dwn4cy.PNG" alt="Image 1" width="880" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lập hồ sơ cho bản build ở môi trường production
&lt;/h3&gt;

&lt;p&gt;Bây giờ hãy chạy &lt;code&gt;npm run build&lt;/code&gt;, sau đó &lt;code&gt;npx serve -s build&lt;/code&gt; và hãy lập hồ sơ ứng dụng một lần nữa! Tôi sẽ làm theo các bước đăng ký giống như lần trước.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wjgzG6Xq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzotw0xajbkxii52tr5p.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wjgzG6Xq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzotw0xajbkxii52tr5p.PNG" alt="Image 6" width="765" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bạn sẽ nhận thấy rằng đây là lần tương tác giống như lần trước (nó hiển thị trang sau khi đăng ký) và chúng tôi đã tăng từ 13,7 mili giây xuống 6,5 mili giây. Cải tiến tốt đẹp!&lt;/p&gt;

&lt;p&gt;Nhưng thành phần &lt;strong&gt;Ẩn danh&lt;/strong&gt; này có gì ở khắp nơi vậy? Và chúng tôi có một thành phần được gọi là &lt;strong&gt;ee&lt;/strong&gt; khác được gọi là &lt;strong&gt;Z&lt;/strong&gt;? Huh? Những gì đang xảy ra ở đây? Chà, bởi vì chúng tôi đang xây dựng ứng dụng của mình cho &lt;strong&gt;production&lt;/strong&gt;, chúng ta đang giảm thiểu mã của mình để tải / phân tích cú pháp nhanh hơn, đây là một điều tốt cho người dùng cuối, nhưng lại là một điều tồi tệ đối với việc đo lường hiệu suất vì điều đó gây khó khăn cho chúng ta để biết thành phần nào trong số những thành phần này là thủ phạm gây ra các vấn đề về hiệu suất.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tắt chức năng name mangling
&lt;/h3&gt;

&lt;p&gt;React biết cách gọi các &lt;strong&gt;components&lt;/strong&gt; của bạn dựa trên thuộc tính &lt;code&gt;name&lt;/code&gt;của &lt;strong&gt;component&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8zGN6Klk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5012qit12wy5yypmszfs.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8zGN6Klk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5012qit12wy5yypmszfs.PNG" alt="Image 7" width="880" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tuy nhiên, khi chúng tôi tạo mã bằng "uglifier" hoặc "minifier", công cụ sẽ thay đổi những tên đó theo cách làm cho code hoạt động giống như trước đây, nhưng giảm kích thước tệp để cải thiện hiệu suất :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nbxthd4d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9j8htfgjq08oy9batvl4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nbxthd4d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9j8htfgjq08oy9batvl4.PNG" alt="Image 8" width="880" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Đây là lý do tại sao chúng ta thấy những cái tên kì quặc này trong các phép đo hiệu suất. Vì vậy, cần phải tắt tính năng mangling này.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;create-react-app&lt;/strong&gt; sử dụng một công cụ có tên là Terser thông qua &lt;strong&gt;terser-webpack-plugin&lt;/strong&gt; để thực hiện việc thu nhỏ, vì vậy chúng ta chỉ cần cập nhật cấu hình để giữ nguyên hàm và tên class.&lt;/p&gt;

&lt;p&gt;Vì vậy, trong cùng một tệp cấu hình webpack đó, hãy cuộn xuống nơi plugin được cấu hình và sửa đổi nó như sau:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hIMgyAPw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjchemv16601a72lr0k1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hIMgyAPw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjchemv16601a72lr0k1.PNG" alt="Image 9" width="880" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Với &lt;strong&gt;keep_classnames&lt;/strong&gt; và &lt;strong&gt;keep_fnames&lt;/strong&gt; được định cấu hình thành true, bây giờ hãy thử build app và chạy một phiên cấu hình một lần nữa!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L5kTTjwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ine3h8fd8p9qh6o3vbk9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L5kTTjwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ine3h8fd8p9qh6o3vbk9.PNG" alt="Image description" width="759" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cạm bẫy: Lập hồ sơ bằng máy tính nhanh
&lt;/h3&gt;

&lt;p&gt;Tôi đảm bảo với bạn rằng hầu hết các bạn đang đọc bài viết này hiện đang phát triển ứng dụng của mình bằng một thiết bị mạnh mẽ hơn hầu hết những người đang sử dụng ứng dụng. Không có gì thay thế cho việc thử ứng dụng của bạn trên các thiết bị mà người dùng sẽ sử dụng. Điều đó nói rằng, bạn có thể hiểu rõ hơn nhiều về hiệu suất thực tế của ứng dụng nếu bạn điều chỉnh CPU để mô phỏng trải nghiệm của một số người dùng ứng dụng của bạn.&lt;/p&gt;

&lt;p&gt;Vì vậy, chúng ta hãy làm điều đó. Ấn vào tab "Performance" của Chrome DevTools, sau đó vào biểu tượng bánh răng để hiển thị cài đặt, sau đó trên tùy chọn CPU, chọn "6x slowdown.".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h3rA5Wqb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3e45w8v4g92ugr4e4lh.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h3rA5Wqb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3e45w8v4g92ugr4e4lh.PNG" alt="Image 11" width="754" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bây giờ hãy làm lại toàn bộ và kiểm tra sự khác biệt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7Dr4pnNW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsvyqpdebtsmo0ue0hu1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7Dr4pnNW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsvyqpdebtsmo0ue0hu1.PNG" alt="Image 12" width="767" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Phù! 31,8 mili giây! Đó là khá chậm! Tìm hiểu thêm về tác động của thời gian đó đối với trải nghiệm của người dùng trong bài đăng blog này có tiêu đề &lt;a href="https://web.dev/rendering-performance/"&gt;Rendering Performance.&lt;/a&gt; Đây có thể là một cái gì đó đáng xem xét! Nhưng chúng tôi sẽ lưu nó cho một bài đăng blog khác 😉&lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Giải thích đơn giản về React.useEffect ()</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Tue, 17 May 2022 13:36:07 +0000</pubDate>
      <link>https://forem.com/buiminh15/giai-thich-don-gian-ve-reactuseeffect--2k4f</link>
      <guid>https://forem.com/buiminh15/giai-thich-don-gian-ve-reactuseeffect--2k4f</guid>
      <description>&lt;p&gt;Bài viết dịch từ:&lt;br&gt;
&lt;a href="https://dmitripavlutin.com/react-useeffect-explanation/" rel="noopener noreferrer"&gt;https://dmitripavlutin.com/react-useeffect-explanation/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1. useEffect () dành cho side-effect
&lt;/h3&gt;

&lt;p&gt;Một component React sử dụng các props và/hoặc state để tính toán kết quả đầu ra. &lt;strong&gt;Nếu component thực hiện các tính toán không nhắm mục đích là giá trị đầu ra, thì các tính toán này được đặt tên là side effect&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ví dụ về các &lt;code&gt;side effect&lt;/code&gt; là lấy data, thao tác DOM trực tiếp, sử dụng các hàm hẹn giờ như setTimeout (), v.v.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component rendering và logic của &lt;code&gt;side effect&lt;/code&gt; là độc lập. Sẽ là một sai lầm nếu thực hiện các &lt;code&gt;side effect&lt;/code&gt; trực tiếp trong phần thân của Component , vốn chủ yếu được sử dụng để tính toán kết quả đầu ra&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tần suất hiển thị của component không phải là điều bạn có thể kiểm soát - nếu React muốn hiển thị component, bạn không thể dừng nó.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Greet({ name }) {
  const message = `Hello, ${name}!`; // Calculates output
  // Bad!
  document.title = `Greetings to ${name}`; // Side-effect!
  return &amp;lt;div&amp;gt;{message}&amp;lt;/div&amp;gt;;       // Calculates output
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Làm thế nào để tách rendering khỏi &lt;code&gt;side effect&lt;/code&gt;? Hãy dùng &lt;br&gt;
&lt;code&gt;useEffect()&lt;/code&gt; - hook chạy các &lt;code&gt;side effect&lt;/code&gt; độc lập với việc rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function Greet({ name }) {
  const message = `Hello, ${name}!`;   // Calculates output
  useEffect(() =&amp;gt; {
    // Good!
    document.title = `Greetings to ${name}`; // Side-effect!
  }, [name]);
  return &amp;lt;div&amp;gt;{message}&amp;lt;/div&amp;gt;;         // Calculates output
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useEffect()&lt;/code&gt; hook chấp nhận 2 đối số:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useEffect(callback[, dependencies]);&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;callback&lt;/code&gt; là hàm chứa logic của &lt;code&gt;side effect&lt;/code&gt;. &lt;code&gt;callback&lt;/code&gt; được thực thi ngay sau khi các thay đổi được đẩy vào DOM.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dependencies&lt;/code&gt; là một mảng tùy chọn của các &lt;code&gt;dependencies&lt;/code&gt; . &lt;code&gt;useEffect()&lt;/code&gt; chỉ thực thi lệnh gọi lại nếu các &lt;code&gt;dependencies&lt;/code&gt; thay đổi giữa các lần hiển thị.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Đặt logic của side effect vào hàm callback, sau đó sử dụng đối số dependencies để kiểm soát thời điểm bạn muốn side effect chạy. Đó là mục đích duy nhất của useEffect().&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.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%2F22swjdpn18jt1w900zsn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F22swjdpn18jt1w900zsn.PNG" alt="Image 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ví dụ: trong đoạn code trước đó, bạn đã thấy &lt;code&gt;useEffect()&lt;/code&gt; đang hoạt động:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  document.title = `Greetings to ${name}`;
}, [name]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cập nhật tiêu đề document là &lt;code&gt;side effect&lt;/code&gt; vì nó không trực tiếp tính toán kết quả đầu ra của component. Đó là lý do tại sao cập nhật tiêu đề document  được đặt trong một hàm callback và được cung cấp cho &lt;code&gt;useEffect()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ngoài ra, bạn không muốn bản cập nhật tiêu đề document thực thi mỗi khi component Greet hiển thị. Bạn chỉ muốn nó được thực thi khi prop name thay đổi - đó là lý do bạn cung cấp tên làm dependency cho &lt;code&gt;useEffect (callback, [name])&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Đối số Dependencies
&lt;/h3&gt;

&lt;p&gt;Đối số &lt;code&gt;Dependencies&lt;/code&gt; của &lt;code&gt;useEffect(callback, dependencies)&lt;/code&gt; cho phép bạn kiểm soát thời điểm &lt;strong&gt;side effect&lt;/strong&gt; chạy. Khi &lt;code&gt;Dependencies&lt;/code&gt; là:&lt;/p&gt;

&lt;h4&gt;
  
  
  A) Không có: Side effect chạy sau mỗi lần rendering
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function MyComponent() {
  useEffect(() =&amp;gt; {
    // Runs after EVERY rendering
  });  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  B) Array rỗng []: side-effect chạy một lần sau lần hiển thị đầu tiên.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function MyComponent() {
  useEffect(() =&amp;gt; {
    // Runs ONCE after initial rendering
  }, []);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  C) Có props hoặc state [prop1, prop2, ..., state1, state2]: side-effect chỉ chạy khi bất kỳ giá trị phụ thuộc nào thay đổi.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from 'react';
function MyComponent({ prop }) {
  const [state, setState] = useState('');
  useEffect(() =&amp;gt; {
    // Runs ONCE after initial rendering
    // and after every rendering ONLY IF `prop` or `state` changes
  }, [prop, state]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hãy phân tích các trường hợp B) và C) vì chúng được sử dụng thường xuyên.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Vòng đời của component
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1 ComponentDidMount
&lt;/h4&gt;

&lt;p&gt;Sử dụng một mảng phụ thuộc trống để gọi một &lt;code&gt;side effect&lt;/code&gt; một lần sau khi component được mount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function Greet({ name }) {
  const message = `Hello, ${name}!`;
  useEffect(() =&amp;gt; {
    // Runs once, after mounting
    document.title = 'Greetings page';
  }, []);
  return &amp;lt;div&amp;gt;{message}&amp;lt;/div&amp;gt;;
}

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

&lt;/div&gt;



&lt;p&gt;useEffect (..., []) được cung cấp một mảng trống làm đối số phụ thuộc. Khi được cấu hình theo cách như vậy, &lt;code&gt;useEffect ()&lt;/code&gt; sẽ thực hiện callback chỉ một lần, sau khi được mount vào DOM.&lt;/p&gt;

&lt;p&gt;Ngay cả khi component hiển thị với thuộc tính &lt;code&gt;name&lt;/code&gt; khác, &lt;strong&gt;side effect&lt;/strong&gt; chỉ chạy một lần sau lần hiển thị đầu tiên:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// First render
&amp;lt;Greet name="Eric" /&amp;gt;   // Side-effect RUNS
// Second render, name prop changes
&amp;lt;Greet name="Stan" /&amp;gt;   // Side-effect DOES NOT RUN
// Third render, name prop changes
&amp;lt;Greet name="Butters"/&amp;gt; // Side-effect DOES NOT RUN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/sweet-jepsen-r8m6t"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h4&gt;
  
  
  3.2 Component did update
&lt;/h4&gt;

&lt;p&gt;Mỗi khi side effect sử dụng props hoặc state, bạn phải chỉ ra các giá trị này dưới dạng dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function MyComponent({ prop }) {
  const [state, setState] = useState();
  useEffect(() =&amp;gt; {
    // Side-effect uses `prop` and `state`
  }, [prop, state]);
  return &amp;lt;div&amp;gt;....&amp;lt;/div&amp;gt;;
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useEffect (callback, [prop, state])&lt;/code&gt; gọi hàm &lt;strong&gt;callback&lt;/strong&gt; sau khi các thay đổi được mount vào DOM và khi và chỉ khi bất kỳ giá trị nào trong mảng phụ thuộc [prop, state] đã thay đổi.&lt;/p&gt;

&lt;p&gt;Sử dụng đối số &lt;strong&gt;dependencies&lt;/strong&gt; của &lt;code&gt;useEffect()&lt;/code&gt;, bạn kiểm soát thời điểm gọi &lt;strong&gt;side effect&lt;/strong&gt;, độc lập với các chu kỳ hiển thị của component. Một lần nữa, đó là bản chất của hook &lt;code&gt;useEffect()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hãy cải thiện component &lt;strong&gt;Greet&lt;/strong&gt; bằng cách sử dụng prop &lt;code&gt;name&lt;/code&gt; trong tiêu đề của document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function Greet({ name }) {
  const message = `Hello, ${name}!`;
  useEffect(() =&amp;gt; {
    document.title = `Greetings to ${name}`; 
  }, [name]);
  return &amp;lt;div&amp;gt;{message}&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prop name được đề cập trong đối số dependencies của &lt;code&gt;useEffect (..., [name])&lt;/code&gt;. &lt;code&gt;useEffect()&lt;/code&gt; hook chạy &lt;strong&gt;side effect&lt;/strong&gt; sau lần hiển thị ban đầu và chỉ khi hiển thị sau khi giá trị &lt;code&gt;name&lt;/code&gt; thay đổi.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/nifty-yonath-mo2qf"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  5, Xóa Side-effect
&lt;/h3&gt;

&lt;p&gt;Một số side-effect cần được xóa: đóng socket, xóa bộ hẹn giờ.&lt;/p&gt;

&lt;p&gt;Nếu &lt;code&gt;callback&lt;/code&gt; của &lt;code&gt;useEffect(callback, deps)&lt;/code&gt;trả về một hàm, thì useEffect () coi đây là xóa side effect:&lt;/p&gt;

&lt;p&gt;Phần xóa side effect (dọn dẹp) hoạt động theo cách sau:&lt;/p&gt;

&lt;p&gt;A) Sau khi rendering ban đầu, &lt;code&gt;useEffect()&lt;/code&gt; gọi hàm callback có side effect. &lt;strong&gt;chức năng dọn dẹp không được gọi&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;B) Trong các lần hiển thị sau đó, trước khi gọi side effect của callback tiếp theo, &lt;code&gt;useEffect()&lt;/code&gt; gọi hàm dọn dẹp từ lần thực thi side effect trước đó (để dọn dẹp mọi thứ sau side effect trước đó), sau đó chạy side effect hiện tại.&lt;/p&gt;

&lt;p&gt;C) Cuối cùng, sau khi component được loại bỏ khỏi DOM &lt;code&gt;useEffect()&lt;/code&gt; gọi hàm dọn dẹp từ side effect mới nhất.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F3esoh31mrkb3wsinehnn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F3esoh31mrkb3wsinehnn.PNG" alt="Image capture 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hãy xem một ví dụ khi dọn dẹp side effect là hữu ích.&lt;/p&gt;

&lt;p&gt;Component sau &lt;code&gt;&amp;lt;RepeatMessage message = "My Message" /&amp;gt;&lt;/code&gt; có props là &lt;code&gt;message&lt;/code&gt;. Sau đó, cứ sau 2 giây, props &lt;code&gt;message&lt;/code&gt; được ghi vào console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function RepeatMessage({ message }) {
  useEffect(() =&amp;gt; {
    setInterval(() =&amp;gt; {
      console.log(message);
    }, 2000);
  }, [message]);
  return &amp;lt;div&amp;gt;I'm logging to console "{message}"&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/restless-wildflower-c0cfw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Ở demo nhập text. Console ghi lại 2 giây một lần bất kỳ message nào đã từng được nhập từ input. Tuy nhiên, bạn chỉ cần log ra message mới nhất.&lt;/p&gt;

&lt;p&gt;Đó là trường hợp để dọn dẹp side effect: hủy bộ hẹn giờ trước đó khi bắt đầu bộ hẹn giờ mới. Hãy trả về một chức năng dọn dẹp dừng bộ đếm thời gian trước đó:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
function RepeatMessage({ message }) {
  useEffect(() =&amp;gt; {
    const id = setInterval(() =&amp;gt; {
      console.log(message);
    }, 2000);
    return () =&amp;gt; {
      clearInterval(id);
    };
  }, [message]);
  return &amp;lt;div&amp;gt;I'm logging to console "{message}"&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/gracious-tdd-gy4zo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Thử trên demo, nhập vào ô input chỉ message mới nhất được log ra.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Ứng dụng của useEffect
&lt;/h3&gt;

&lt;h4&gt;
  
  
  6.1 Fetching data
&lt;/h4&gt;

&lt;p&gt;useEffect() có thể thực hiện side effect là lấy dữ liệu.&lt;/p&gt;

&lt;p&gt;Component &lt;strong&gt;FetchEmployees&lt;/strong&gt; lấy danh sách nhân viên:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from 'react';
function FetchEmployees() {
  const [employees, setEmployees] = useState([]);
  useEffect(() =&amp;gt; {
    async function fetchEmployees() {
      const response = await fetch('/employees');
      const fetchedEmployees = await response.json(response);
      setEmployees(fetchedEmployees);
    }
    fetchEmployees();
  }, []);
  return (
    &amp;lt;div&amp;gt;
      {employees.map(name =&amp;gt; &amp;lt;div&amp;gt;{name}&amp;lt;/div&amp;gt;)}
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;useEffect() bắt đầu lấy data từ request bằng cách gọi hàm bất đồng bộ fetchEmployees() sau lần khởi tạo ban đầu.&lt;/p&gt;

&lt;p&gt;Khi request hoàn tất, &lt;code&gt;setEmployees(fetchedEmployees)&lt;/code&gt; sẽ cập nhật state của nhân viên với danh sách nhân viên vừa lấy được.&lt;/p&gt;

&lt;p&gt;Lưu ý rằng đối số callback của &lt;code&gt;useEffect(callback)&lt;/code&gt; không thể là một hàm bất đồng bộ. Nhưng bạn luôn có thể định nghĩa và sau đó gọi một hàm bất đồng bộ bên trong chính callback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function FetchEmployees() {
  const [employees, setEmployees] = useState([]);
  useEffect(() =&amp;gt; {  // &amp;lt;--- CANNOT be an async function
    async function fetchEmployees() {
      // ...
    }
    fetchEmployees(); // &amp;lt;--- But CAN invoke async functions
  }, []);
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Để get data từ props hoặc state, chỉ cần chỉ ra dependencies trong đối số dependencies : useEffect (fetchSideEffect, [prop, stateValue]).&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Kết luận
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useEffect(callback, dependencies)&lt;/code&gt; là hook quản lý các &lt;strong&gt;side effect&lt;/strong&gt; trong các component chức năng. đối số &lt;strong&gt;callback&lt;/strong&gt; là một hàm để đặt &lt;strong&gt;logic của side effect&lt;/strong&gt;. &lt;strong&gt;dependencies&lt;/strong&gt; là danh sách các phụ thuộc của &lt;strong&gt;side effect&lt;/strong&gt; của bạn: là props hoặc state.&lt;/p&gt;

&lt;p&gt;useEffect(callback, dependencies) gọi lại sau khi gắn vào DOM lần đầu và trong các lần rendering sau đó, nếu bất kỳ giá trị nào bên trong các dependencies thay đổi.&lt;/p&gt;

</description>
      <category>react</category>
      <category>hook</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Error Boundaries</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Mon, 16 May 2022 01:59:14 +0000</pubDate>
      <link>https://forem.com/buiminh15/error-boundaries-576h</link>
      <guid>https://forem.com/buiminh15/error-boundaries-576h</guid>
      <description>&lt;p&gt;Bài viết dịch từ:&lt;br&gt;
&lt;a href="https://reactjs.org/docs/error-boundaries.html"&gt;https://reactjs.org/docs/error-boundaries.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trước đây, các lỗi JavaScript bên trong các component thường làm hỏng trạng thái bên trong của React và khiến nó phát ra các lỗi khó hiểu trong lần hiển thị tiếp theo. Những lỗi này gây ra do lỗi trước đó trong code gây ra, nhưng React không cung cấp cách xử lý chúng một cách linh hoạt trong các component và không thể khôi phục chúng.&lt;/p&gt;
&lt;h3&gt;
  
  
  Giới thiệu Error Boundaries
&lt;/h3&gt;

&lt;p&gt;Lỗi JavaScript trong một phần của giao diện người dùng không nên làm hỏng toàn bộ ứng dụng. Để giải quyết vấn đề này cho người dùng React, React 16 giới thiệu một khái niệm mới về “Error Boundaries”.&lt;/p&gt;

&lt;p&gt;Error Boundaries là các component React bắt lỗi JavaScript ở bất kỳ đâu trong cây component con của chúng, ghi lại các lỗi đó và hiển thị giao diện người dùng dự phòng thay vì cây component bị lỗi. Error Boundaries bắt lỗi trong quá trình rendering, trong các phương thức vòng đời và trong các hàm tạo của toàn bộ cây bên dưới chúng.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Error Boundaries không bắt lỗi đối với:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event handlers (learn more)&lt;/li&gt;
&lt;li&gt;Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)&lt;/li&gt;
&lt;li&gt;Server side rendering&lt;/li&gt;
&lt;li&gt;Errors thrown in the error boundary itself (rather than its children)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Class component sẽ trở thành error boundary nếu nó định nghĩa một trong hai (hoặc cả hai) phương thức vòng đời &lt;code&gt;static getDerivedStateFromError ()&lt;/code&gt; hoặc &lt;code&gt;componentDidCatch ()&lt;/code&gt;. Sử dụng &lt;code&gt;static getDerivedStateFromError ()&lt;/code&gt; để hiển thị một giao diện người dùng dự phòng sau khi một lỗi được đưa ra. Sử dụng &lt;code&gt;componentDidCatch ()&lt;/code&gt; để ghi thông tin lỗi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return &amp;lt;h1&amp;gt;Something went wrong.&amp;lt;/h1&amp;gt;;
    }

    return this.props.children; 
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sau đó, bạn có thể sử dụng nó như một component thông thường:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ErrorBoundary&amp;gt;
  &amp;lt;MyWidget /&amp;gt;
&amp;lt;/ErrorBoundary&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Các error boundaries hoạt động giống như JavaScript catch{}, nhưng đối với component. Chỉ các class component mới có thể là error boundaries. Trong thực tế, hầu hết thời gian bạn sẽ muốn khai báo ErrorBoundary một lần và sử dụng nó trong toàn bộ ứng dụng của mình.&lt;/p&gt;

&lt;p&gt;Lưu ý rằng &lt;strong&gt;Error Boundaries&lt;/strong&gt; chỉ bắt lỗi trong các component bên dưới chúng trong cây. &lt;strong&gt;Error Boundary&lt;/strong&gt; không thể tự bắt lỗi. Nếu một &lt;strong&gt;Error Boundary&lt;/strong&gt; không thể hiển thị thông báo lỗi, lỗi sẽ lan truyền đến &lt;strong&gt;Error Boundary&lt;/strong&gt; gần nhất phía trên nó. Điều này cũng tương tự như cách khối catch {} hoạt động trong JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://codepen.io/gaearon/pen/wqvxGa?editors=0010"&gt;Example&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Nơi đặt Error Boundaries
&lt;/h3&gt;

&lt;p&gt;Mức độ chi tiết của Error Boundary là tùy thuộc vào bạn. Bạn có thể bao bọc các component tuyến cấp cao nhất để hiển thị thông báo "Đã xảy ra sự cố" cho người dùng, giống như cách phía máy chủ thường xử lý các sự cố. Bạn cũng có thể bao bọc các widget riêng lẻ trong một Error Boundary để bảo vệ chúng khỏi làm hỏng phần còn lại của ứng dụng.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Điều này là tùy vào người viết, có thể đặt ở tầng trên cùng của ứng dụng để bắt toàn bộ lỗi, cũng có thể đặt sâu hơn để bắt lỗi cho cụ thể.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Hành vi mới cho các lỗi chưa xảy ra
&lt;/h3&gt;

&lt;p&gt;Sự thay đổi này có một hàm ý quan trọng. Kể từ React 16, các lỗi không nằm trong bất kỳ Error Boundaries nào sẽ dẫn đến việc ngắt kết nối toàn bộ cây component React.&lt;/p&gt;

&lt;p&gt;Chúng tôi đã tranh luận về quyết định này, nhưng theo kinh nghiệm của chúng tôi, việc để lại giao diện người dùng bị hỏng tại chỗ còn tệ hơn là xóa bỏ hoàn toàn. Ví dụ: trong một sản phẩm như Messenger, việc hiển thị giao diện người dùng bị hỏng có thể dẫn đến việc ai đó gửi tin nhắn đến nhầm người. Tương tự, ứng dụng thanh toán hiển thị sai số tiền còn tệ hơn là không hiển thị gì.&lt;/p&gt;

&lt;p&gt;Thay đổi này có nghĩa là khi bạn chuyển sang React 16, bạn có thể sẽ phát hiện ra các lỗi hiện có trong ứng dụng của mình mà trước đây chưa được chú ý. Thêm Error Boundaries cho phép bạn cung cấp trải nghiệm người dùng tốt hơn khi có sự cố.&lt;/p&gt;

&lt;p&gt;Ví dụ: Facebook Messenger bọc nội dung của sidebar, bảng thông tin, nhật ký cuộc trò chuyện và đầu vào tin nhắn thành các Error Boundaries riêng biệt. Nếu một số thành phần trong một trong các khu vực giao diện người dùng này gặp sự cố, phần còn lại của chúng vẫn tương tác.&lt;/p&gt;

&lt;p&gt;Chúng tôi cũng khuyến khích bạn sử dụng các dịch vụ báo cáo lỗi JS (hoặc xây dựng của riêng bạn) để bạn có thể tìm hiểu về các trường hợp ngoại lệ không được khắc phục khi chúng xảy ra trong quá trình sản xuất và khắc phục chúng.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component Stack Traces
&lt;/h3&gt;

&lt;p&gt;React 16 in tất cả các lỗi xảy ra trong quá trình hiển thị cho console ở môi trường phát triển. Ngoài thông báo lỗi và JavaScript stack, nó cũng cung cấp component stack traces. Bây giờ bạn có thể thấy vị trí chính xác lỗi trong cây component:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aNpWI_mt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rplw70in9clp1krx3cc4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aNpWI_mt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rplw70in9clp1krx3cc4.png" alt="Image eb" width="840" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bạn cũng có thể xem tên tệp và số dòng trong component stack trace. Điều này hoạt động theo mặc định trong Create React App:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rCVphhP8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdhiqkol8b997o83qt8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rCVphhP8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdhiqkol8b997o83qt8o.png" alt="Image eb-1" width="840" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nếu không sử dụng Create React App, bạn có thể thêm &lt;a href="https://www.npmjs.com/package/@babel/plugin-transform-react-jsx-source"&gt;plugin&lt;/a&gt; này theo cách thủ công vào cấu hình Babel của mình. Lưu ý rằng nó chỉ dành cho mục đích development và phải bị vô hiệu hóa trong production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thế còn try/catch
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;try / catch&lt;/code&gt; dùng cho &lt;code&gt;imperative code&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
  showButton();
} catch (error) {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tuy nhiên, các component React là &lt;strong&gt;declarative&lt;/strong&gt; và chỉ định những gì sẽ được hiển thị:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Button /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tham khảo: &lt;a href="https://viblo.asia/p/so-sanh-imperative-programming-va-declarative-programming-YWOZro3ElQ0"&gt;declarative  vs imperative&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Thế còn Event Handlers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error Boundary&lt;/strong&gt; không bắt lỗi bên trong &lt;strong&gt;Event Handlers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;React không cần &lt;strong&gt;Error Boundary&lt;/strong&gt; để khôi phục từ lỗi trong &lt;strong&gt;Event Handlers&lt;/strong&gt;. Không giống như &lt;strong&gt;phương thức render và phương thức lifecycle&lt;/strong&gt;, &lt;strong&gt;Event Handlers&lt;/strong&gt; không xảy ra trong quá trình rendering. Vì vậy, nếu &lt;strong&gt;event handler&lt;/strong&gt; ném ra lỗi, React vẫn biết những gì sẽ hiển thị trên màn hình.&lt;/p&gt;

&lt;p&gt;Nếu bạn cần bắt lỗi bên trong &lt;strong&gt;Event Handlers&lt;/strong&gt;, hãy sử dụng câu lệnh &lt;code&gt;try / catch&lt;/code&gt; JavaScript thông thường:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    try {
      // Do something that could throw
    } catch (error) {
      this.setState({ error });
    }
  }

  render() {
    if (this.state.error) {
      return &amp;lt;h1&amp;gt;Caught an error.&amp;lt;/h1&amp;gt;
    }
    return &amp;lt;button onClick={this.handleClick}&amp;gt;Click Me&amp;lt;/button&amp;gt;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lưu ý rằng ví dụ trên thể hiện hành vi JavaScript thông thường và không sử dụng các Error Boundary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dự án để học Error Boundary: &lt;a href="https://github.com/rowyio/rowy/blob/main/src/components/ErrorBoundary.tsx"&gt;Github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Cách đặt khoảng thời gian trong React (setInterval)(có ví dụ)</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Sun, 15 May 2022 15:02:54 +0000</pubDate>
      <link>https://forem.com/buiminh15/cach-dat-khoang-thoi-gian-trong-react-co-vi-du-4p0m</link>
      <guid>https://forem.com/buiminh15/cach-dat-khoang-thoi-gian-trong-react-co-vi-du-4p0m</guid>
      <description>&lt;p&gt;Bài viết được dịch từ:&lt;br&gt;
&lt;a href="https://devtrium.com/posts/set-interval-react"&gt;https://devtrium.com/posts/set-interval-react&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sử dụng &lt;code&gt;setInterval&lt;/code&gt; cho phép bạn thực thi một hàm trong những khoảng thời gian cụ thể. Nó thường rất hữu ích trong các ứng dụng React, chẳng hạn như để kiểm tra một điều kiện thường xuyên hoặc lấy dữ liệu thường xuyên.&lt;/p&gt;
&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;

&lt;p&gt;Đây là cách bạn sử dụng setInterval trong một component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;· · ·
useEffect(() =&amp;gt; {
  const interval = setInterval(() =&amp;gt; {
    console.log('This will be called every 2 seconds');
  }, 2000);

  return () =&amp;gt; clearInterval(interval);
}, []);
· · ·
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Đọc phần còn lại của bài viết nếu bạn muốn lời giải thích về những gì đang xảy ra ở trên!&lt;/p&gt;

&lt;h3&gt;
  
  
  Cách hoạt động của &lt;code&gt;setInterval&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Có ba câu hỏi được đặt ra:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tại sao &lt;code&gt;setInterval&lt;/code&gt; được gọi bên trong hook &lt;code&gt;useEffect&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Tại sao gọi hàm &lt;code&gt;setInterval&lt;/code&gt; lại trông như vậy?&lt;/li&gt;
&lt;li&gt;Tại sao chúng ta trả lại một cái gì đó từ hook &lt;code&gt;useEffect&lt;/code&gt;?&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1. Tại sao &lt;code&gt;setInterval&lt;/code&gt; được gọi bên trong hook &lt;code&gt;useEffect&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Theo tài liệu React, "Effect Hook cho phép bạn thực hiện các side-effect trong các thành phần chức năng". Và đó chính xác là những gì chúng tôi muốn làm ở đây.&lt;/p&gt;

&lt;p&gt;Bạn có thể hỏi điều gì sẽ xảy ra nếu chúng ta khai báo nó trong chính component. Hãy xem điều đó với các ví dụ nổi tiếng nhất, một bộ đếm!&lt;/p&gt;

&lt;p&gt;Giả sử chúng ta muốn một bộ đếm bắt đầu từ 0 và tăng lên 1 sau mỗi giây.&lt;/p&gt;

&lt;p&gt;Cách triển khai bộ đếm này bằng cách sử dụng code ở đầu bài viết như sau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from 'react';

export default function ExampleCounter() {
  const [counter, setCounter] = useState(0);

  useEffect(() =&amp;gt; {
    const interval = setInterval(() =&amp;gt; {
      setCounter((prevCounter) =&amp;gt; prevCounter + 1);
    }, 1000);

    return () =&amp;gt; clearInterval(interval);
  }, []);

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;h1&amp;gt;Counter: {counter}&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Một functional component khá đơn giản giữ state trong bộ đếm. State được tăng lên mỗi giây nhờ &lt;code&gt;setInterval&lt;/code&gt; được xác định trong &lt;code&gt;useEffect&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Bây giờ điều gì sẽ xảy ra nếu tôi loại bỏ hoàn toàn &lt;code&gt;useEffect&lt;/code&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';

export default function ExampleCounter() {
  const [counter, setCounter] = useState(0);

  setInterval(() =&amp;gt; {
    setCounter((prevCounter) =&amp;gt; prevCounter + 1);
  }, 1000);

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;h1&amp;gt;Counter: {counter}&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chà, điều này xảy ra:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Key0j9hg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87m18l0w0fcovzlrmr6a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Key0j9hg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87m18l0w0fcovzlrmr6a.gif" alt="Image counter-crazy" width="450" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Đúng là một bộ đếm điên rồ! bạn có thể đoán được chuyện gì đã xảy ra không?&lt;/p&gt;

&lt;p&gt;Vì &lt;code&gt;setInterval&lt;/code&gt; được định nghĩa trực tiếp bên trong functional component, nó được gọi mỗi khi component render! Và component render khi nào? Khi state thay đổi! Và khi nào thì state thay đổi? Khi interval callback được gọi.&lt;/p&gt;

&lt;p&gt;Vậy nên để side-effect trong &lt;code&gt;useEffect&lt;/code&gt; nếu bạn không muốn side-effect bị gọi mỗi lần component renders.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Tại sao gọi hàm &lt;code&gt;setInterval&lt;/code&gt; lại trông như vậy?
&lt;/h4&gt;

&lt;p&gt;Điều này khá dễ dàng: nó chỉ đơn giản là (sử dụng API web của setInterval)[&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/setInterval"&gt;https://developer.mozilla.org/en-US/docs/Web/API/setInterval&lt;/a&gt;]. Có một số chức năng được định nghĩa cho bạn trên web mà bạn có thể trực tiếp sử dụng. &lt;code&gt;setInterval&lt;/code&gt; là một trong số đó.&lt;/p&gt;

&lt;p&gt;Hàm nhận hai đối số:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Đầu tiên là một hàm sẽ được gọi trong các khoảng thời gian xác định.&lt;/li&gt;
&lt;li&gt;Thứ hai là khoảng thời gian, tính bằng mili giây.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3. Tại sao chúng ta trả lại một cái gì đó từ hook &lt;code&gt;useEffect&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Xin nhắc lại, khi chúng ta muốn thực hiện một số hành động khi một component bị hủy, chúng ta xác định nó trong một hàm được trả về trong &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Một trường hợp sử dụng rất phổ biến của điều này là xóa các effect như khoảng thời gian.&lt;/p&gt;

&lt;p&gt;Tại sao chúng ta cần xóa các khoảng thời gian? Vâng, hãy tưởng tượng chúng ta không xóa nó. Component bị hủy, nhưng khoảng thời gian vẫn chạy! Và nó đang cố gắng thiết lập một state không tồn tại nữa.&lt;/p&gt;

&lt;p&gt;Bản thân đây không phải là vấn đề quá lớn (React sẽ bỏ qua nó), nhưng nó vẫn là một điểm rò rỉ bộ nhớ. Bây giờ hãy tưởng tượng thành phần được tạo và phá hủy lặp đi lặp lại. Bạn có thể nhận được hàng tá setIntervals đang chạy! Tổng hợp lại, điều này có thể làm chậm ứng dụng của bạn một cách nghiêm trọng.&lt;/p&gt;

&lt;p&gt;Đó là lý do tại sao API web cung cấp cho chúng ta &lt;code&gt;setInterval&lt;/code&gt; cũng cung cấp cho chúng tôi một hàm &lt;code&gt;clearInterval&lt;/code&gt;. Và đó là lý do tại sao bạn gọi nó trong câu lệnh trả về &lt;code&gt;useEffect&lt;/code&gt;!&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hướng dẫn hoàn chỉnh để sử dụngRef () và Refs trong React</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Sun, 15 May 2022 11:40:52 +0000</pubDate>
      <link>https://forem.com/buiminh15/huong-dan-hoan-chinh-de-su-dungref-va-refs-trong-react-2pp9</link>
      <guid>https://forem.com/buiminh15/huong-dan-hoan-chinh-de-su-dungref-va-refs-trong-react-2pp9</guid>
      <description>&lt;p&gt;Bài viết dịch từ trang: &lt;br&gt;
&lt;a href="https://dmitripavlutin.com/react-useref-guide/"&gt;https://dmitripavlutin.com/react-useref-guide/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trong bài đăng này, bạn sẽ học cách sử dụng hook &lt;code&gt;React.useRef ()&lt;/code&gt; để tạo các giá trị có thể thay đổi liên tục (còn được gọi là tham chiếu hoặc &lt;code&gt;refs&lt;/code&gt;), cũng như truy cập các phần tử DOM.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Mutable values
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useRef&lt;/code&gt; (initialValue) là một hook React tích hợp sẵn chấp nhận một đối số làm giá trị ban đầu và trả về một tham chiếu (còn gọi là ref). Ref là một đối tượng có thuộc tính đặc biệt là &lt;code&gt;current&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef } from 'react';
function MyComponent() {
  const reference = useRef(initialValue);
  const someHandler = () =&amp;gt; {
    // Access reference value:
    const value = reference.current;
    // Update reference value:
    reference.current = newValue;
  };
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;reference.current&lt;/code&gt; truy cập vào giá trị tham chiếu và &lt;code&gt;reference.current = newValue&lt;/code&gt; cập nhật giá trị tham chiếu. Khá đơn giản.&lt;/p&gt;

&lt;p&gt;Có 2 quy tắc cần nhớ về references:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Giá trị của tham chiếu được duy trì (giữ nguyên) giữa các lần re-rendering component;&lt;/li&gt;
&lt;li&gt;Cập nhật tham chiếu &lt;strong&gt;không làm re-rendering component&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bây giờ, chúng ta hãy xem cách sử dụng &lt;code&gt;useRef ()&lt;/code&gt; trong thực tế.&lt;/p&gt;

&lt;h4&gt;
  
  
  1.1 Trường hợp sử dụng: ghi nhật ký button khi click
&lt;/h4&gt;

&lt;p&gt;Component &lt;code&gt;LogButtonClicks&lt;/code&gt; sử dụng một tham chiếu để lưu trữ số lần ấn vào button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef } from 'react';
function LogButtonClicks() {
  const countRef = useRef(0);

  const handle = () =&amp;gt; {
    countRef.current++;
    console.log(`Clicked ${countRef.current} times`);
  };
  console.log('I rendered!');
  return &amp;lt;button onClick={handle}&amp;gt;Click me&amp;lt;/button&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/logging-button-clicks-reference-ogcnc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const countRef = useRef (0)&lt;/code&gt; tạo một tham chiếu countRef được khởi tạo bằng 0.&lt;/p&gt;

&lt;p&gt;Khi button được ấn, hàm xử lý được gọi và giá trị tham chiếu được tăng lên: &lt;code&gt;countRef.current ++&lt;/code&gt;. Giá trị tham chiếu được ghi vào console.&lt;/p&gt;

&lt;p&gt;Cập nhật giá trị tham chiếu &lt;code&gt;countRef.current ++&lt;/code&gt; không làm component re-rendering. Điều này được chứng minh bằng thực tế là &lt;strong&gt;'I rendered!'&lt;/strong&gt; được ghi vào console chỉ một lần, ở lần hiển thị đầu tiên và không có render nào xảy ra khi tham chiếu được cập nhật.&lt;/p&gt;

&lt;p&gt;Bây giờ có một câu hỏi: sự khác biệt chính giữa tham chiếu và state là gì?&lt;/p&gt;

&lt;h3&gt;
  
  
  Khác biệt giữa tham chiếu và state
&lt;/h3&gt;

&lt;p&gt;Hãy sử dụng lại component &lt;code&gt;LogButtonClicks&lt;/code&gt; từ phần trước, nhưng lần này sử dụng hook &lt;code&gt;useState ()&lt;/code&gt; để đếm số lần ấn vào button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';
function LogButtonClicks() {
  const [count, setCount] = useState(0);

  const handle = () =&amp;gt; {
    const updatedCount = count + 1;
    console.log(`Clicked ${updatedCount} times`);
    setCount(updatedCount);
  };
  console.log('I rendered!');
  return &amp;lt;button onClick={handle}&amp;gt;Click me&amp;lt;/button&amp;gt;;
}

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

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/logging-button-clicks-state-nzzuk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Ở link trên ấn vào button. Mỗi lần bạn ấn vào, bạn sẽ thấy trong console có thông báo &lt;strong&gt;'I rendered!'&lt;/strong&gt; - nghĩa là mỗi khi state được cập nhật, component sẽ re-render.&lt;/p&gt;

&lt;p&gt;Vì vậy, 2 điểm khác biệt chính giữa tham chiếu và trạng thái:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Cập nhật tham chiếu không làm re-render, trong khi cập nhật state làm cho component re-render;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cập nhật tham chiếu là đồng bộ (giá trị tham chiếu được cập nhật có sẵn ngay lập tức), trong khi cập nhật state là không đồng bộ (state được cập nhật sau khi re-render).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Từ một quan điểm cao hơn, các tham chiếu lưu trữ dữ liệu cơ sở hạ tầng về side-effect, trong khi state lưu trữ thông tin được hiển thị trực tiếp trên màn hình.&lt;/p&gt;

&lt;h4&gt;
  
  
  1.2 Trường hợp sử dụng: triển khai đồng hồ bấm giờ
&lt;/h4&gt;

&lt;p&gt;Bạn có thể lưu trữ bên trong một cơ sở hạ tầng dữ liệu tham khảo về các side-effect. Ví dụ: bạn có thể lưu trữ vào các con trỏ tham chiếu: timer ids, socket ids, etc.&lt;/p&gt;

&lt;p&gt;Component &lt;code&gt;Stopwatch&lt;/code&gt; sử dụng chức năng hẹn giờ &lt;code&gt;setInterval&lt;/code&gt;(gọi lại, thời gian) để tăng số đếm của đồng hồ bấm giờ mỗi giây. Id bộ hẹn giờ được lưu trữ trong &lt;code&gt;timerIdRef&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef, useState, useEffect } from 'react';
function Stopwatch() {
  const timerIdRef = useRef(0);
  const [count, setCount] = useState(0);
  const startHandler = () =&amp;gt; {
    if (timerIdRef.current) { return; }
    timerIdRef.current = setInterval(() =&amp;gt; setCount(c =&amp;gt; c+1), 1000);
  };
  const stopHandler = () =&amp;gt; {
    clearInterval(timerIdRef.current);
    timerIdRef.current = 0;
  };
  useEffect(() =&amp;gt; {
    return () =&amp;gt; clearInterval(timerIdRef.current);
  }, []);
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;Timer: {count}s&amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;button onClick={startHandler}&amp;gt;Start&amp;lt;/button&amp;gt;
        &amp;lt;button onClick={stopHandler}&amp;gt;Stop&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/stopwatch-cm7zz"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;startHandler ()&lt;/code&gt;, được gọi khi ấn vào button Start, khởi động bộ hẹn giờ và lưu id bộ hẹn giờ trong tham chiếu &lt;code&gt;timerIdRef.current = setInterval (...)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Để dừng đồng hồ bấm giờ, người dùng ấn vào button Stop. Trình xử lý button Stop &lt;code&gt;stopHandler ()&lt;/code&gt; truy cập id bộ hẹn giờ từ tham chiếu và dừng bộ hẹn giờ &lt;code&gt;clearInterval(timerIdRef.current)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ngoài ra, nếu component unmount khi đồng hồ bấm giờ đang hoạt động, chức năng dọn dẹp của &lt;code&gt;useEffect ()&lt;/code&gt; cũng sẽ dừng đồng hồ bấm giờ.&lt;/p&gt;

&lt;p&gt;Trong ví dụ về đồng hồ bấm giờ, tham chiếu được sử dụng để lưu trữ dữ liệu cơ sở hạ tầng - id bộ hẹn giờ hoạt động.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Truy cập các phần tử DOM
&lt;/h3&gt;

&lt;p&gt;Một ứng dụng hữu ích khác của hook &lt;code&gt;useRef ()&lt;/code&gt; là truy cập các phần tử DOM. Điều này được thực hiện trong 3 bước:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Xác định tham chiếu để truy cập phần tử &lt;code&gt;const elementRef = useRef ()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Gán tham chiếu đến thuộc tính ref của phần tử: &lt;code&gt;&amp;lt;div ref = {elementRef}&amp;gt; &amp;lt;/div&amp;gt;&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Sau khi gắn kết, &lt;code&gt;elementRef.current&lt;/code&gt; trỏ đến phần tử DOM.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef, useEffect } from 'react';
function AccessingElement() {
  const elementRef = useRef();
   useEffect(() =&amp;gt; {
    const divElement = elementRef.current;
    console.log(divElement); // logs &amp;lt;div&amp;gt;I'm an element&amp;lt;/div&amp;gt;
  }, []);
  return (
    &amp;lt;div ref={elementRef}&amp;gt;
      I'm an element
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/access-dom-element-hrh78"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;2.1 Trường hợp sử dụng: focus vào input&lt;/p&gt;

&lt;p&gt;Ví dụ, bạn sẽ cần truy cập các phần tử DOM để focus vào input  khi component mount.&lt;/p&gt;

&lt;p&gt;Để làm cho nó hoạt động, bạn sẽ cần tạo một tham chiếu đến input, gán tham chiếu cho thuộc tính &lt;code&gt;ref&lt;/code&gt; và sau khi gắn kết, hãy gọi phương thức đặc biệt &lt;code&gt;element.focus ()&lt;/code&gt; trên phần tử.&lt;/p&gt;

&lt;p&gt;Đây là cách triển khai có thể có của component &lt;code&gt;&amp;lt;InputFocus&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef, useEffect } from 'react';
function InputFocus() {
  const inputRef = useRef();
  useEffect(() =&amp;gt; {
    inputRef.current.focus();
  }, []);
  return (
    &amp;lt;input 
      ref={inputRef} 
      type="text" 
    /&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/input-focus-zntci"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const inputRef = useRef ()&lt;/code&gt; tạo một tham chiếu để giữ phần tử &lt;code&gt;input&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;inputRef&lt;/code&gt; sau đó được gán cho thuộc tính &lt;code&gt;ref&lt;/code&gt; của input: &lt;code&gt;&amp;lt;input ref = {inputRef} type = "text" /&amp;gt;.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;React sau đó, sau khi mounting, đặt &lt;code&gt;inputRef.current&lt;/code&gt; là phần tử input. Bây giờ bạn có thể đặt focus qua: &lt;code&gt;inputRef.current.focus ()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tham chiếu không có giá trị khi hiển thị ban đầu
&lt;/h3&gt;

&lt;p&gt;Trong quá trình hiển thị ban đầu, tham chiếu được cho là giữ phần tử DOM là rỗng:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef, useEffect } from 'react';
function InputFocus() {
  const inputRef = useRef();
  useEffect(() =&amp;gt; {
    // Logs `HTMLInputElement` 
    console.log(inputRef.current);
    inputRef.current.focus();
  }, []);
  // Logs `undefined` during initial rendering
  console.log(inputRef.current);
  return &amp;lt;input ref={inputRef} type="text" /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/empty-on-initial-rendering-5my4g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Trong quá trình hiển thị ban đầu, React vẫn xác định đâu là đầu ra của component, vì vậy chưa có cấu trúc DOM nào được tạo. Đó là lý do tại sao &lt;code&gt;inputRef.current&lt;/code&gt; đánh giá là không xác định trong quá trình hiển thị ban đầu.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useEffect (callback, [])&lt;/code&gt; hook gọi lại ngay sau khi mount, khi phần tử input đã được tạo trong DOM.&lt;/p&gt;

&lt;p&gt;hàm callback của &lt;code&gt;useEffect (callback, [])&lt;/code&gt; là nơi thích hợp để truy cập inputRef.current vì nó được đảm bảo rằng DOM được xây dựng.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hạn chế cập nhật refs
&lt;/h3&gt;

&lt;p&gt;Phạm vi chức năng của component chức năng nên tính toán đầu ra hoặc gọi các hook.&lt;/p&gt;

&lt;p&gt;Đó là lý do tại sao việc cập nhật một tham chiếu (cũng như cập nhật state) không nên được thực hiện bên trong phạm vi ngay lập tức của chức năng của component.&lt;/p&gt;

&lt;p&gt;Tham chiếu phải được cập nhật bên trong callback &lt;code&gt;useEffect ()&lt;/code&gt; hoặc bên trong các handlers (event handlers, timer handlers, etc).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef, useEffect } from 'react';
function MyComponent({ prop }) {
  const myRef = useRef(0);
  useEffect(() =&amp;gt; {
    myRef.current++; // Good!
    setTimeout(() =&amp;gt; {
      myRef.current++; // Good!
    }, 1000);
  }, []);
  const handler = () =&amp;gt; {
    myRef.current++; // Good!
  };
  myRef.current++; // Bad!
  if (prop) {
    myRef.current++; // Bad!
  }
  return &amp;lt;button onClick={handler}&amp;gt;My button&amp;lt;/button&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Tóm tắt
&lt;/h3&gt;

&lt;p&gt;useRef () hook tạo ra các tham chiếu.&lt;/p&gt;

&lt;p&gt;Gọi &lt;code&gt;const reference = useRef(initialValue)&lt;/code&gt; với &lt;code&gt;initialValue&lt;/code&gt; trả về một đối tượng đặc biệt có tên là &lt;code&gt;tham chiếu&lt;/code&gt;. Đối tượng tham chiếu có thuộc tính &lt;code&gt;current&lt;/code&gt;: bạn có thể sử dụng thuộc tính này để đọc giá trị tham chiếu &lt;code&gt;reference.current&lt;/code&gt; hoặc cập nhật tham chiếu &lt;code&gt;reference.current = newValue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Giữa các lần component re-rendering, giá trị của tham chiếu là không đổi.&lt;/p&gt;

&lt;p&gt;Cập nhật tham chiếu, trái với cập nhật state, không làm component re-rendering.&lt;/p&gt;

&lt;p&gt;Ref cũng có thể truy cập các phần tử DOM. Gán tham chiếu đến thuộc tính &lt;code&gt;ref&lt;/code&gt; của phần tử bạn muốn truy cập: &lt;code&gt;&amp;lt;div ref = {reference}&amp;gt; Element&amp;lt;/div&amp;gt;&lt;/code&gt; - và phần tử sẽ có tại &lt;code&gt;reference.current&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>hook</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Nghệ thuật dựng component trong thực tế-Phần 4</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Sat, 14 May 2022 22:46:12 +0000</pubDate>
      <link>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-4-131a</link>
      <guid>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-4-131a</guid>
      <description>&lt;p&gt;Bài viết được dịch từ:&lt;br&gt;
&lt;a href="https://ishadeed.com/article/building-real-life-components/"&gt;https://ishadeed.com/article/building-real-life-components/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Nội dung từ phải sang trái
&lt;/h3&gt;

&lt;p&gt;Trong trường hợp bố cục là LTR (Từ trái sang phải) và nội dung tin nhắn bằng tiếng Ả Rập, hướng của nội dung tin nhắn phải là RTL (Từ phải sang trái).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F8nox-Vo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rd4n8bcdyumcmdlwm0f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F8nox-Vo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rd4n8bcdyumcmdlwm0f.png" alt="Image rtl" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vì phần tử &lt;code&gt;.card__content__start&lt;/code&gt; là một flex container, các item con sẽ tự động lật tùy thuộc vào &lt;code&gt;direction&lt;/code&gt; của component hoặc phần tử gốc (root element). Điều này có thể được thêm một cách chủ động tùy thuộc vào ngôn ngữ nội dung. &lt;code&gt;(Chú ý: css direction)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card__content"&amp;gt;
  &amp;lt;div class="card__content__start" style="direction: rtl"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div class="card__content__end"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lật component
&lt;/h3&gt;

&lt;p&gt;Nếu người dùng chọn RTL (Từ phải sang trái) như tiếng Ả Rập cho toàn bộ giao diện người dùng, thì component sẽ được lật.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F0TLKYkI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptuzddgdxaedw9c9u97o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F0TLKYkI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptuzddgdxaedw9c9u97o.png" alt="Image rtl1" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vì flexbox được sử dụng để sắp xếp các mục, không cần thực hiện nhiều thao tác ngoại trừ việc lật margin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* LTR */
.card__content__end {
  margin-left: 12px;
}

/* LTR */
.card__content__end {
  margin-right: 12px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chi tiết về khả năng tiếp cận
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Sử dụng bàn phím
&lt;/h4&gt;

&lt;p&gt;Để xây dựng một sản phẩm hoạt động với hàng tỷ người dùng, nó phải hoàn toàn có thể truy cập được. Đối với component của bài viết này, tôi đã thử nghiệm trong Chrome và Firefox và nhận thấy các vấn đề sau:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Các kiểu tiêu điểm hoạt động tốt trong Chrome, nhưng trong Firefox, không có manh mối trực quan nào về chúng.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Menu tác vụ xuất hiện khi di chuột có thể đặt tiêu điểm trong Firefox và tôi không thể truy cập menu này bằng bàn phím trong Chrome.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cOamxQYZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9rh90kap2mvvsrrdnph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cOamxQYZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9rh90kap2mvvsrrdnph.png" alt="Image a11" width="880" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Và để cung cấp cho bạn nhiều ngữ cảnh hơn, menu tác vụ sẽ xuất hiện khi di chuột. Tuy nhiên, là một người dùng bàn phím, tôi cũng mong đợi có thể truy cập nó qua bàn phím.&lt;/p&gt;

&lt;p&gt;Rất tiếc, trong Chrome, tôi không thể truy cập menu tác vụ.&lt;/p&gt;

&lt;h4&gt;
  
  
  Danh sách cards
&lt;/h4&gt;

&lt;p&gt;Trong danh sách card component, có một số role ARIA được sử dụng. Danh sách là ở dạng grid và nó chứa các hàng. Mỗi hàng có thể có một hoặc nhiều ô.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div role="grid"&amp;gt;
  &amp;lt;div role="row"&amp;gt;
    &amp;lt;div role="gridcell"&amp;gt;
      &amp;lt;a href="#"&amp;gt;
        &amp;lt;!-- The component lives here --&amp;gt;
      &amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div role="row"&amp;gt;
    &amp;lt;div role="gridcell"&amp;gt;
      &amp;lt;a href="#"&amp;gt;
        &amp;lt;!-- The component lives here --&amp;gt;
      &amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Nhiều hình đại diện
&lt;/h4&gt;

&lt;p&gt;Đối với trò chuyện nhóm, có nhiều hình đại diện cho các chỉ số được nhìn thấy. Trong trường hợp này, các hình đại diện được sắp xếp dưới dạng các ô của một hàng bằng cách sử dụng role ARIA.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div role="grid"&amp;gt;
  &amp;lt;div role="row"&amp;gt;
    &amp;lt;!-- 1st avatar --&amp;gt;
    &amp;lt;div role="cell"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;!-- 2nd avatar --&amp;gt;
    &amp;lt;div role="cell"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Đây là bản &lt;a href="https://codepen.io/shadeed/pen/rNMvKqL?editors=1010"&gt;demo&lt;/a&gt; trên Codepen. Nó không bao gồm tất cả các biến thể. Tôi chỉ đang thử nghiệm mọi thứ.&lt;/p&gt;

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

&lt;p&gt;Xây dựng web bằng HTML &amp;amp; CSS không phải là một công việc dễ dàng và cũng không khó. Điểm tôi muốn đưa ra trong bài viết này là component đơn giản nhất bao gồm rất nhiều công việc. Nhân tiện, tất cả các giải thích ở trên chỉ thảo luận về HTML &amp;amp; CSS. Còn JavaScript thì sao? Đó là một câu chuyện khác.&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>component</category>
      <category>react</category>
    </item>
    <item>
      <title>Cách sử dụng Chrome Dev Tools để tìm các nút thắt về hiệu suất</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Sat, 14 May 2022 08:43:23 +0000</pubDate>
      <link>https://forem.com/buiminh15/cach-su-dung-chrome-dev-tools-de-tim-cac-nut-that-ve-hieu-suat-306i</link>
      <guid>https://forem.com/buiminh15/cach-su-dung-chrome-dev-tools-de-tim-cac-nut-that-ve-hieu-suat-306i</guid>
      <description>&lt;p&gt;Bài viết dịch từ trang:&lt;br&gt;
&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-chrome-dev-tools-to-find-performance-bottlenecks"&gt;https://www.digitalocean.com/community/tutorials/how-to-use-chrome-dev-tools-to-find-performance-bottlenecks&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bài viết này viết về tab Audit hiện đã được thay bằng tab LightHouse. Do mình không tìm được bài viết chi tiết về cách sử dụng LightHouse nên mình sẽ dịch bài này. Audit và LightHouse khá là giống nhau nên các bạn có thể tham khảo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Giới thiệu
&lt;/h3&gt;

&lt;p&gt;Khi một người tiến bộ trong sự nghiệp phát triển phần mềm, có thể nảy sinh những mối quan tâm ngoài việc code. Trong thế giới phát triển web, không chỉ xây dựng phần mềm chức năng mà còn phải làm cho nó có hiệu suất cao để có thể liên tục mang lại trải nghiệm mong muốn trong khi vẫn sử dụng tài nguyên tối thiểu.&lt;/p&gt;

&lt;p&gt;Thông thường, đây sẽ là một nhiệm vụ khá lớn vì người ta không thể đưa ra dự đoán về các thuộc tính tiêu thụ tài nguyên của một ứng dụng nếu không có các công cụ để mô phỏng và đo lường các thông số khác nhau.&lt;/p&gt;

&lt;p&gt;Trong bài viết này, bạn sẽ khám phá một trong những công cụ sau: Chrome Dev Tools. Cụ thể, bạn sẽ học được tính tiện dụng của tab &lt;strong&gt;Audits&lt;/strong&gt; và &lt;strong&gt;Performance&lt;/strong&gt; trong việc đánh giá các ứng dụng web và phát hiện các vấn đề về hiệu suất.&lt;/p&gt;

&lt;p&gt;Để làm cho bài kiểm tra này trở thành một bài kiểm tra thực tế, bạn sẽ thử nghiệm các kỹ thuật khác nhau để tìm ra các vấn đề về hiệu suất trên một trang web và giải quyết chúng. Hướng dẫn này khám phá trang web &lt;strong&gt;Scotch.io&lt;/strong&gt;, nhưng các bước này có thể được áp dụng cho bất kỳ trang web nào.&lt;/p&gt;

&lt;h3&gt;
  
  
  Điều kiện tiên quyết
&lt;/h3&gt;

&lt;p&gt;Cần cài đặt Google Chrome browser trước.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bước 1 - Chuẩn bị trình duyệt
&lt;/h4&gt;

&lt;p&gt;Khi cải thiện hiệu suất của một trang web hoặc ứng dụng web, có hai khía cạnh chính cần xem xét:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hiệu suất tải&lt;/li&gt;
&lt;li&gt;Hiệu suất thời gian chạy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hướng dẫn này sẽ tập trung nhiều hơn vào Hiệu suất tải. Hiệu suất tải đề cập đến hiệu suất của trang khi nó đang tải. Mục tiêu chính là xác định các vấn đề về hiệu suất ảnh hưởng đến tốc độ ứng dụng và trải nghiệm người dùng tổng thể.&lt;/p&gt;

&lt;p&gt;Để bắt đầu kiểm tra Hiệu suất tải, bạn sẽ bắt đầu bằng cách thiết lập kiểm tra &lt;strong&gt;(Audit)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Khởi chạy trình duyệt Chrome của bạn và mở một tab ở chế độ Ẩn danh bằng cách nhấn &lt;strong&gt;COMMAND + SHIFT + N trên macOS&lt;/strong&gt; hoặc &lt;strong&gt;CTRL + SHIFT + N trên Windows hoặc Linux&lt;/strong&gt;. Sau khi trình duyệt Ẩn danh được mở, hãy điều hướng đến trang web mà bạn muốn kiểm tra.&lt;/p&gt;

&lt;p&gt;Tiếp theo, mở DevTools bằng cách nhấn &lt;strong&gt;COMMAND + OPTION + I trên macOS&lt;/strong&gt; hoặc &lt;strong&gt;CTRL + SHIFT + I trên Windows hoặc Linux&lt;/strong&gt;. Nếu bạn muốn thay đổi vị trí của bảng điều khiển DevTools, hãy nhấp vào ba chấm dọc trên thanh công cụ và thực hiện lựa chọn từ tùy chọn &lt;strong&gt;Dock Side&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sau khi bạn hài lòng với vị trí bảng điều khiển, hãy chuyển sang tab Kiểm tra &lt;strong&gt;(Audits)&lt;/strong&gt;. Với sự trợ giúp của công cụ này, bạn sẽ tạo đường cơ sở để đo lường các thay đổi ứng dụng tiếp theo, cũng như nhận được thông tin chi tiết về những thay đổi nào sẽ cải thiện ứng dụng.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lưu ý: Tab Kiểm tra có thể bị ẩn sau nút mũi tên Bảng khác (More Panels).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CxtPofYH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axkitu368unuygaxxb81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CxtPofYH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axkitu368unuygaxxb81.png" alt="Image devtools-1" width="880" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mục tiêu chính của bạn ở đây là xác định các điểm nghẽn về hiệu suất trên trang &lt;code&gt;Scotch.io&lt;/code&gt; và tối ưu hóa để có hiệu suất tốt hơn. Một nút thắt, trong kỹ thuật phần mềm, mô tả một tình huống mà dung lượng của một ứng dụng bị giới hạn bởi một component duy nhất.&lt;/p&gt;

&lt;p&gt;Trong bước tiếp theo, bạn sẽ thực hiện kiểm tra để tìm kiếm các điểm nghẽn về hiệu suất.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bước 2 - Thực hiện Kiểm tra
&lt;/h4&gt;

&lt;p&gt;Khi thực hiện kiểm tra, bạn sẽ sử dụng một công cụ có tên là &lt;strong&gt;Lighthouse&lt;/strong&gt;. &lt;strong&gt;Lighthouse&lt;/strong&gt; là một công cụ tự động mã nguồn mở để cải thiện chất lượng của bất kỳ trang web nào trong các lĩnh vực hiệu suất, khả năng truy cập, các tính năng web và hơn thế nữa.&lt;/p&gt;

&lt;p&gt;Trong tab Kiểm tra &lt;strong&gt;(Audits)&lt;/strong&gt; của &lt;strong&gt;Chrome Dev Tools&lt;/strong&gt;, hãy cấu hình công cụ kiểm tra (Audits). Cài đặt default như sau:&lt;/p&gt;

&lt;h5&gt;
  
  
  Thiết bị
&lt;/h5&gt;

&lt;p&gt;Có tùy chọn chuyển đổi giữa Mobile và Desktop. Hơn một nửa lưu lượng truy cập web tính đến quý 3 năm 2018 là do Thiết bị di động tạo ra, vì vậy chúng tôi sẽ kiểm tra Scotch.io trên Mobile.&lt;/p&gt;

&lt;h5&gt;
  
  
  Kiểm tra (Audits)
&lt;/h5&gt;

&lt;p&gt;Cài đặt này cho phép chúng ta chọn chất lượng của ứng dụng mà chúng tôi muốn đánh giá và cải thiện. Trong trường hợp này, hiệu suất là mối quan tâm chính, vì vậy bạn có thể bỏ chọn mọi tùy chọn khác.&lt;/p&gt;

&lt;h5&gt;
  
  
  Throttling
&lt;/h5&gt;

&lt;p&gt;Tùy chọn này cho phép bạn mô phỏng các điều kiện duyệt web trên thiết bị di động. Bạn sẽ sử dụng tùy chọn &lt;code&gt;Sim Simulated Fast 3G&lt;/code&gt;, &lt;code&gt;4x CPU Slowdown&lt;/code&gt;. Điều này thực sự sẽ không hiệu quả trong quá trình kiểm tra, nhưng nó sẽ giúp tính toán thời gian tải trang trong điều kiện thiết bị di động.&lt;/p&gt;

&lt;h5&gt;
  
  
  Xóa Lưu trữ
&lt;/h5&gt;

&lt;p&gt;Điều này cho phép bạn xóa tất cả dữ liệu được lưu trong bộ nhớ cache và tài nguyên trang web thử nghiệm, để kiểm tra đối với khách lần đầu truy cập sẽ có trải nghiệm như nào, vì vậy hãy chọn tùy chọn này nếu nó chưa được chọn.&lt;/p&gt;

&lt;p&gt;Sau khi định cấu hình kiểm tra như đã chỉ định ở trên, hãy ấn &lt;strong&gt;Generate report&lt;/strong&gt; và đợi trong khi Audit chuẩn bị báo cáo chi tiết về hiệu suất của trang web.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bước 3 - Phân tích Báo cáo đánh giá
&lt;/h4&gt;

&lt;p&gt;Sau khi hoàn thành kiểm tra, báo cáo sẽ có dạng như sau:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Jy1H246--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvrxod418vcvzc3lmwwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Jy1H246--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvrxod418vcvzc3lmwwy.png" alt="Image dev-tools-2" width="825" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con số trong một vòng tròn ở trên cùng bên phải cho biết điểm hiệu suất tổng thể của trang web trên thang điểm từ 1–100. Chúng ta hiện có 55, điều này cho thấy rằng có một cơ hội để cải thiện cùng với các đề xuất được cung cấp để tăng điểm số và hiệu suất. Hãy chia báo cáo thành các phần và phân tích chúng riêng lẻ.&lt;/p&gt;

&lt;p&gt;Trong phần &lt;strong&gt;Metrics&lt;/strong&gt;, bạn sẽ tìm thấy thông tin chi tiết định lượng về các khía cạnh khác nhau về hiệu suất của trang web:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2THMOUPp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj0vej8so0tewice9pc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2THMOUPp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj0vej8so0tewice9pc6.png" alt="Image devtools3" width="825" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ngay bên dưới phần &lt;strong&gt;Metrics&lt;/strong&gt; là một nhóm ảnh chụp màn hình hiển thị các trạng thái giao diện người dùng khác nhau của trang từ thời điểm truy vấn ban đầu cho đến khi tải hoàn toàn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mNgOiHFE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/umxhdk2wj51uzhp007kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mNgOiHFE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/umxhdk2wj51uzhp007kl.png" alt="Image devtools4" width="825" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Phần &lt;strong&gt;Diagnostics&lt;/strong&gt; cung cấp cho bạn thông tin bổ sung về hiệu suất, thường chỉ ra các yếu tố xác định thời gian tải của trang web:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8NZHOSpg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wf895c1l0muxsdwjxbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8NZHOSpg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wf895c1l0muxsdwjxbs.png" alt="Image devtools5" width="825" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuối cùng, phần &lt;strong&gt;Audits&lt;/strong&gt; đạt yêu cầu nêu bật các kiểm tra hiệu suất đã được trang web vượt qua:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hFQENkY5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbdbg0bxsd83sn6zd4xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hFQENkY5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbdbg0bxsd83sn6zd4xf.png" alt="Image devtools6" width="825" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Với bản báo cáo, bạn biết những vấn đề nào có thể cần được giải quyết.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bước 4 - Giải quyết vấn đề trong phần Metrics
&lt;/h4&gt;

&lt;p&gt;Trong ví dụ này, năm vấn đề về hiệu suất đã được đánh dấu. Trong bước này, chúng tôi sẽ khám phá các bản sửa lỗi có thể có:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fOm8AP8O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o50xyrl5u5th1n7swx0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fOm8AP8O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o50xyrl5u5th1n7swx0i.png" alt="Image devtools7" width="825" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  First Meaningful Paint
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;First Meaningful Paint&lt;/strong&gt; cho bạn biết khi nào nội dung chính của trang nhìn thấy được. Theo đánh giá, bạn sẽ mất khoảng &lt;strong&gt;3,4 giây&lt;/strong&gt; trước khi xem nội dung chính. Điều này có thể được xác nhận bằng cách nhấp vào button &lt;strong&gt;View Trace&lt;/strong&gt;. Thao tác này sẽ đưa bạn đến tab &lt;strong&gt;Performance&lt;/strong&gt;, nơi bạn có thể xem qua các trạng thái giao diện người dùng khác nhau trong thời gian tải để xác nhận điều gì xảy ra tại từng thời điểm cụ thể.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UNFDK9zh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tegteg6gpd9dbw7tlb7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UNFDK9zh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tegteg6gpd9dbw7tlb7o.png" alt="Image devtools8" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lưu ý rằng đó là lúc nội dung trang được hiển thị.&lt;/p&gt;

&lt;p&gt;Để cải thiện điều này, chúng tôi phải tối ưu hóa đường dẫn hiển thị quan trọng của trang / ứng dụng tổng thể. Điều này có nghĩa là chúng ta ưu tiên hiển thị nội dung theo mong muốn của người dùng nhằm tạo ra trải nghiệm tốt hơn và cải thiện hiệu suất. Điều này có thể được thực hiện bằng cách giảm số lượng tài nguyên quan trọng, độ dài đường dẫn quan trọng và số byte quan trọng.&lt;/p&gt;

&lt;h5&gt;
  
  
  Speed Index
&lt;/h5&gt;

&lt;p&gt;Speed Index cho biết nội dung trang được hiển thị nhanh như thế nào. Quá trình này mất khoảng 7,2 giây như được hiển thị trên tab hiệu suất:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FF0SHTcO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7x15b0llrhi45izz55qc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FF0SHTcO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7x15b0llrhi45izz55qc.png" alt="Image devtools9" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Một cách để khắc phục điều này, giống như trong số liệu đã kiểm tra trước đó, là tối ưu hóa đường dẫn hiển thị quan trọng. Cách thứ hai là tối ưu hóa hiệu quả nội dung. Điều này liên quan đến việc loại bỏ các bản tải xuống không cần thiết theo cách thủ công, tối ưu hóa mã hóa truyền tải thông qua nén và lưu vào bộ nhớ đệm bất cứ khi nào có thể để ngăn tải lại các tài nguyên không thay đổi.&lt;/p&gt;

&lt;h5&gt;
  
  
  First CPU Idle
&lt;/h5&gt;

&lt;p&gt;Còn được gọi là &lt;strong&gt;First Interactive&lt;/strong&gt;, &lt;strong&gt;First CPU Idle&lt;/strong&gt; cho bạn biết khi nào trang trở nên tương tác tối thiểu (CPU không hoạt động đủ để xử lý thông tin nhập của người dùng, như nhấp chuột, vuốt, v.v.). Từ quá trình kiểm tra, quá trình này mất khoảng 6,5 giây. Giảm giá trị này xuống mức tối thiểu luôn tốt hơn:&lt;/p&gt;

&lt;h5&gt;
  
  
  Time to Interactive
&lt;/h5&gt;

&lt;p&gt;Time to Interactive cho biết thời gian cần thiết để trang có thể tương tác hoàn toàn. Quá trình kiểm tra trong ví dụ này cho thấy 6,9 giây cho số liệu này. Tương tác trong ngữ cảnh này mô tả điểm mà:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trang đã hiển thị nội dung hữu ích.&lt;/li&gt;
&lt;li&gt;Trình xử lý sự kiện được gán cho hầu hết các phần tử hiển thị trên trang.&lt;/li&gt;
&lt;li&gt;Trang phản hồi các tương tác của người dùng trong vòng 50 mili giây.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CN153-jg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7uy6wx2cbrxnlo06ujoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CN153-jg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7uy6wx2cbrxnlo06ujoj.png" alt="Image devtools10" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Để khắc phục điều này, bạn cần loại bỏ những công việc JavaScript không cần thiết xảy ra trong quá trình tải trang. Điều này thường có thể đạt được bằng cách &lt;strong&gt;code splitting&lt;/strong&gt; và &lt;strong&gt;lazy loading&lt;/strong&gt; (Ai làm React nhớ cho cái này vào nhé), nén, rút ​​gọn và bằng cách xóa code không sử dụng (bảo sao phải cài eslint) và bộ nhớ đệm không sử dụng. &lt;/p&gt;

&lt;h5&gt;
  
  
  Estimated Input Latency
&lt;/h5&gt;

&lt;p&gt;Estimated Input Latency mô tả khả năng đáp ứng của ứng dụng đối với đầu vào của người dùng. Quá trình kiểm tra ghi lại khoảng 170 mili giây trên số liệu này. Các ứng dụng thường có 100 mili giây để phản hồi thông tin nhập của người dùng, tuy nhiên, mục tiêu cho Lighthouse là 50 mili giây. Lý do cho sự chênh lệch này là do Lighthouse sử dụng chỉ số proxy, là tính khả dụng của luồng chính để đánh giá chỉ số này thay vì đo lường trực tiếp.&lt;/p&gt;

&lt;p&gt;Sau khi mất nhiều thời gian hơn thời gian quy định, ứng dụng có thể bị coi là chậm.&lt;/p&gt;

&lt;p&gt;Để cải thiện số liệu này, bạn có thể sử dụng &lt;strong&gt;service worker&lt;/strong&gt; thực hiện một số tính toán, để giải phóng luồng chính. Một biện pháp hữu ích khác là cấu trúc lại &lt;strong&gt;CSS selectors&lt;/strong&gt; để đảm bảo chúng thực hiện ít phép tính hơn.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bước 5 - Giải quyết các vấn đề trong phần Opportunities
&lt;/h4&gt;

&lt;p&gt;Phần Opportunities  liệt kê các tối ưu hóa có thể cải thiện hiệu suất:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O_Z1x_oN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rs9461ec9ys5ce5h9r3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O_Z1x_oN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rs9461ec9ys5ce5h9r3.png" alt="Image devtools12" width="825" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thông thường, khi các trang web tải, chúng sẽ kết nối với các nguồn khác (server) để nhận hoặc gửi dữ liệu. Để cải thiện hiệu suất như trong trường hợp này, cách tốt nhất là thông báo cho trình duyệt để thiết lập kết nối với các server như vậy sớm hơn trong quá trình hiển thị, do đó cắt giảm lượng thời gian chờ giải quyết các tra cứu DNS, chuyển hướng và một số lần quay lại và hơn thế nữa cho đến khi khách hàng nhận được phản hồi.&lt;/p&gt;

&lt;p&gt;Để khắc phục điều này, bạn có thể thông báo cho trình duyệt về ý định sử dụng các tài nguyên đó bằng cách thêm thuộc tính &lt;code&gt;rel&lt;/code&gt; vào các thẻ liên kết như được hiển thị bên dưới:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;link rel="preconnect" href="https://scotchresources.com"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Trên các kết nối an toàn, quá trình này vẫn có thể mất một chút thời gian, vì vậy nó phải được sử dụng trong vòng 10 giây, nếu không trình duyệt sẽ tự động đóng kết nối và tất cả công việc kết nối ban đầu sẽ trở nên lãng phí.&lt;/p&gt;

</description>
      <category>optimize</category>
      <category>react</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Nghệ thuật dựng component trong thực tế-Phần 3</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Fri, 13 May 2022 09:03:02 +0000</pubDate>
      <link>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-3-44ob</link>
      <guid>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-3-44ob</guid>
      <description>&lt;p&gt;Bài viết được dịch từ:&lt;br&gt;
&lt;a href="https://ishadeed.com/article/building-real-life-components/"&gt;https://ishadeed.com/article/building-real-life-components/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Nhiều hình đại diện trong trò chuyện nhóm
&lt;/h3&gt;

&lt;p&gt;Trong trường hợp trò chuyện với nhiều người, khu vực hình đại diện sẽ có hai hình đại diện với mỗi hình đại diện được đặt lần lượt ở trên cùng bên phải và dưới cùng bên trái.&lt;/p&gt;

&lt;p&gt;Để giữ cho một hình đại diện và nhiều hình đại diện được căn chỉnh, chúng ta cần đặt một kích thước cố định cho thẻ cha chứa nhiều hình đại diện.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card__avatar {
  width: 56px;
  height: 56px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mpWPXpWb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5qzsg10ti1hydqnxd1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mpWPXpWb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5qzsg10ti1hydqnxd1n.png" alt="Image multiple-avatar" width="880" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Biến thể này yêu cầu thay đổi HTML, xem đoạn code HTML dưới.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card__avatar card__avatar--multiple"&amp;gt;
  &amp;lt;svg
    class="avatar avatar-1"
    role="none"
    style="height: 36px; width: 36px"
  &amp;gt;&amp;lt;/svg&amp;gt;
  &amp;lt;svg
    class="avatar avatar-2"
    role="none"
    style="height: 36px; width: 36px"
  &amp;gt;&amp;lt;/svg&amp;gt;
  &amp;lt;div class="badge"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card__avatar--multiple {
  position: relative;
  width: 56px;
  height: 56px;
}

.card__avatar--multiple .avatar {
  position: absolute;
}

.card__avatar--multiple .avatar-1 {
  right: 0;
  top: 0;
}

.card__avatar--multiple .avatar-2 {
  left: 0;
  bottom: 0;
}

.card__avatar--multiple .badge {
  right: 6px;
  bottom: 6px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kpX4aMVq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00vk0sqdpj8jes0fn7on.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kpX4aMVq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00vk0sqdpj8jes0fn7on.png" alt="Image multiple-avatar-2" width="880" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Nội dung
&lt;/h3&gt;

&lt;p&gt;Khu vực này là nơi người dùng có thể nhìn thấy tên của người mà họ đang trò chuyện và nội dung của tin nhắn hoặc hành động (không rõ lắm chắc là status).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hwVQ3eim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyln2i1qjsse7vzb3tsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hwVQ3eim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyln2i1qjsse7vzb3tsk.png" alt="Image content-area" width="880" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tôi có thể tưởng tượng phần code HTML này được chia thành hai phần, một phần cho nội dung văn bản (tên, tin nhắn hoặc hành động) và phần thứ hai cho chỉ báo ở phía bên phải (tin nhắn mới, đã xem, đã tắt tiếng, đã gửi).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TUuDewpN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvrqoznjasxl6q6nju66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TUuDewpN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvrqoznjasxl6q6nju66.png" alt="Image content-area-2" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Phần đầu tiên
&lt;/h4&gt;

&lt;p&gt;Hãy cùng khám phá code HTML cho khu vực nội dung.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card__content"&amp;gt;
  &amp;lt;div class="card__content__start"&amp;gt;
    &amp;lt;h3&amp;gt;Ahmad Shadeed&amp;lt;/h3&amp;gt;
    &amp;lt;div class="row"&amp;gt;
      &amp;lt;p&amp;gt;You: Thanks, sounds good. What about doing a webinar, too?&amp;lt;/p&amp;gt;
      &amp;lt;span class="separator"&amp;gt;.&amp;lt;/span&amp;gt;
      &amp;lt;time&amp;gt;8hr&amp;lt;/time&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class="card__content__end"&amp;gt;
    &amp;lt;!-- The indicator (new message, seen, muted, sent) --&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card__content {
  display: flex;
  flex: 1;
}

.card__content__start {
  display: flex;
  flex: 1;
}

.card__content__start .row {
  display: flex;
  align-items: center;
}

.card__content__end {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-left: 12px;
}

.separator {
  margin-left: 4px;
  margin-right: 4px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Với phần trên, khu vực nội dung sẽ giống như bên dưới (Đây là ảnh chụp màn hình được chụp từ Firefox).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YTa7b00e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kewuculhqpug7ef4h2sc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YTa7b00e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kewuculhqpug7ef4h2sc.png" alt="Image content-area-3" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Độ dài của tên hoặc tin nhắn có thể rất dài. Quan trọng là phải tính đến điều đó ngay từ đầu. Trước tiên, chúng ta hãy khám phá phương pháp "flow as you like".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SZV0nltC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9x3c0nqueeyyn9d732y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SZV0nltC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9x3c0nqueeyyn9d732y.png" alt="Image content-area-4" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trong hình trên, nội dung thẻ thứ hai bao gồm nhiều dòng. Điều này có vẻ không tốt cho một component. Để tránh điều đó, đây là những thứ cần làm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Đặt &lt;code&gt;min-width: 0&lt;/code&gt; trên các item con (dùng flex cho parent component). Vì sao? Tôi sẽ cho bạn biết sau đây.&lt;/li&gt;
&lt;li&gt;Cắt bớt văn bản bằng cách sử dụng các thuộc tính &lt;code&gt;overflow&lt;/code&gt;, &lt;code&gt;white-space&lt;/code&gt; và &lt;code&gt;text-overflow&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tôi thêm code CSS cho phần Tên và ở thẻ &lt;code&gt;p&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card__content__start h3,
.card__content__start p {
  overflow-x: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tuy nhiên, điều này không thể giải quyết vấn đề khi chúng ta đang sử dụng flexbox. Lưu ý kết quả sau khi áp dụng CSS ở trên:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M-Lh6GKA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iini1lz771yj6z82lcax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M-Lh6GKA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iini1lz771yj6z82lcax.png" alt="Image content-area-5" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lý do là các &lt;code&gt;flex items&lt;/code&gt; sẽ không thu nhỏ dưới &lt;strong&gt;kích thước nội dung tối thiểu của chúng&lt;/strong&gt;. Để giải quyết vấn đề này, chúng ta cần đặt &lt;code&gt;min-width: 0&lt;/code&gt; trên các phần tử &lt;code&gt;.card__content&lt;/code&gt; và &lt;code&gt;card__content__start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DEFI5BER--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2ot76sytf2to6bgfcbl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DEFI5BER--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2ot76sytf2to6bgfcbl.png" alt="Image content-area-6" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Phần thứ hai
&lt;/h4&gt;

&lt;p&gt;Mỗi tin nhắn có một indicator (status) và chúng ta nên tính đến tất cả chúng. Đây là tất cả các indicator mà tôi biết. Có thể còn nhiều điều mà tôi không biết (Nếu có, vui lòng cho tôi biết).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jTIUK-m7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/708fkjyldjy5usdl21f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jTIUK-m7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/708fkjyldjy5usdl21f3.png" alt="Image message-status" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Đối với phần này, chúng ta sẽ tập trung vào phần tử &lt;code&gt;.card__content__end&lt;/code&gt; và nội dung bên trong 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;&amp;lt;div class="card__content"&amp;gt;
  &amp;lt;div class="card__content__start"&amp;gt;
    &amp;lt;!-- The name and message --&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class="card__content__end"&amp;gt;
    &amp;lt;!-- The indicator (new message, seen, muted, sent) --&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bằng cách có một phần tử chung, bất kỳ component nào cũng có thể đặt trong nó. Phần tử &lt;code&gt;.card__content__end&lt;/code&gt; không được có bất kỳ styles nào như color hoặc font, nó sẽ chỉ đóng vai trò là ngôi nhà cho một component cụ thể.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tin nhắn mới
&lt;/h4&gt;

&lt;p&gt;Trong khi kiểm tra cách Facebook thực hiện chỉ báo (indicator) tin nhắn mới, hóa ra đó là một button có nhãn “Mark as read”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div role="button" aria-label="Mark as read" tabindex="0"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U3FtQEKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p9t1a9p0eyxxjawac4f5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U3FtQEKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p9t1a9p0eyxxjawac4f5.png" alt="Image new-message" width="880" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tôi không hiểu bối cảnh tại sao nhóm tại Facebook lại chọn một phần tử &lt;code&gt;div&lt;/code&gt; thay vì một phần tử &lt;code&gt;button&lt;/code&gt; thực tế. Với &lt;code&gt;button&lt;/code&gt;, chúng ta không cần sử dụng &lt;code&gt;role&lt;/code&gt;, &lt;code&gt;aria-label&lt;/code&gt; và &lt;code&gt;tabindex&lt;/code&gt;. Thay vào đó, tất cả những thứ đó đều có sẵn miễn phí.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hình đại diện Seen
&lt;/h4&gt;

&lt;p&gt;Tương tự như hình đại diện của người dùng, hình đại diện Seen không có gì khác biệt. Nó sử dụng phần tử &lt;code&gt;svg&lt;/code&gt; cho hình đại diện có nhãn &lt;code&gt;aria-label&lt;/code&gt; cho biết tên của người dùng.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dgNJtIrK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/46w4dl61nwqahnwcs8va.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dgNJtIrK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/46w4dl61nwqahnwcs8va.png" alt="Image signle-seen" width="880" height="365"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg aria-label="Ahmad Shadeed" role="img"&amp;gt;
  &amp;lt;!-- Mask and image --&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Nhiều hình đại diện Seen
&lt;/h4&gt;

&lt;p&gt;Thành thật mà nói, đây là một trong những yêu thích của tôi. Tôi thực sự thích cách team tại Facebook thực hiện nó.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7_CNL-96--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00k7w6su0nh8nj4rhph4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7_CNL-96--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00k7w6su0nh8nj4rhph4.png" alt="Image multiple-seen" width="880" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bạn có nhận thấy đường viền giữa hai hình đại diện không? Ngay từ cái nhìn đầu tiên, bạn có thể nghĩ rằng đây là đường viền bởi CSS cho hình đại diện đầu tiên. Nếu bạn nghĩ như vậy, rất tiếc phải thông báo cho bạn biết rằng bạn đã sai (đúng như suy nghĩ ban đầu của tôi).&lt;/p&gt;

&lt;p&gt;Điều này có được do áp dụng SVG mask.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg role="none"&amp;gt;
  &amp;lt;mask id="circle"&amp;gt;
    &amp;lt;circle cx="8" cy="8" fill="white" r="8"&amp;gt;&amp;lt;/circle&amp;gt;
    &amp;lt;circle cx="-4" cy="8" fill="black" r="10"&amp;gt;&amp;lt;/circle&amp;gt;
  &amp;lt;/mask&amp;gt;

  &amp;lt;g mask="url(#circle)"&amp;gt;
    &amp;lt;image&amp;gt;&amp;lt;/image&amp;gt;
    &amp;lt;circle class="border" cx="28" cy="28" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
  &amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Đây là hình ảnh về cách hoạt động của nó.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vE2M076o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyzya73kdy8zfqsrrz71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vE2M076o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyzya73kdy8zfqsrrz71.png" alt="Image multiple-seen-2" width="880" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thật đáng kinh ngạc. Phải không? Tôi thực sự thích sử dụng SVG cho trường hợp cụ thể như này.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hết phần 3
&lt;/h3&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>component</category>
      <category>react</category>
    </item>
    <item>
      <title>Nghệ thuật dựng component trong thực tế-Phần 2</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Wed, 11 May 2022 07:46:12 +0000</pubDate>
      <link>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-2-jo1</link>
      <guid>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-2-jo1</guid>
      <description>&lt;p&gt;Bài viết được dịch từ:&lt;br&gt;
&lt;a href="https://ishadeed.com/article/building-real-life-components/"&gt;https://ishadeed.com/article/building-real-life-components/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Các khu vực của component
&lt;/h3&gt;

&lt;p&gt;Để triển khai một component chuẩn, trước tiên chúng ta cần suy nghĩ kỹ về HTML trước. Trong trường hợp này, chúng ta có hai khu vực của &lt;strong&gt;component&lt;/strong&gt; có nhiều biến thể đó là hình đại diện và khu vực nội dung.&lt;/p&gt;
&lt;h4&gt;
  
  
  Ảnh đại diện
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hDEfZWiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0bbrlc89gen7ph7o5z5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hDEfZWiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0bbrlc89gen7ph7o5z5.png" alt="Image avatar-1" width="880" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Để code HTML cho phần avatar, trước tiên chúng ta cần hiểu các trạng thái của nó. Dưới đây là các biến thể có thể có:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hình đại diện duy nhất&lt;/li&gt;
&lt;li&gt;Hình đại diện duy nhất có trạng thái trực tuyến&lt;/li&gt;
&lt;li&gt;Nhiều hình đại diện cho trò chuyện nhóm&lt;/li&gt;
&lt;li&gt;Nhiều hình đại diện có trạng thái trực tuyến&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Xem xét đoạn HTML sau, chúng ta muốn đảm bảo rằng &lt;code&gt;.card__avatar&lt;/code&gt; có thể xử lý tất cả các biến thể ở trên.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card"&amp;gt;
  &amp;lt;div class="card__avatar"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div class="card__content"&amp;gt;
    &amp;lt;!-- Name, message, badge.. --&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Hình đại diện duy nhất
&lt;/h5&gt;

&lt;p&gt;Hãy tập trung vào biến thể đầu tiên, đó là một hình đại diện duy nhất. Hình đại diện phải có đường viền bên trong (hoặc bóng trong) để làm cho nó trông giống như một vòng tròn ngay cả khi hình đại diện được sử dụng toàn màu trắng.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TH4c_hPS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imvnm651vjhr0zkzfrqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TH4c_hPS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imvnm651vjhr0zkzfrqu.png" alt="Image avatar-2" width="880" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trong CSS, không thể áp dụng &lt;code&gt;box-shadow&lt;/code&gt; (inner) cho phần tử &lt;code&gt;img&lt;/code&gt;. Chúng ta có hai lựa chọn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sử dụng thêm một thẻ &lt;code&gt;div&lt;/code&gt; có đường viền trong suốt.&lt;/li&gt;
&lt;li&gt;Sử dụng thẻ &lt;code&gt;svg&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mục tiêu nếu đường viền bên trong là hiển thị đường viền xung quanh hình đại diện trong các trường hợp:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hình đại diện toàn màu trắng ở chế độ ánh sáng&lt;/li&gt;
&lt;li&gt;hình đại diện toàn màu đen ở chế độ tối&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A8hiZimA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vqu72t9eeloc01ues1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A8hiZimA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vqu72t9eeloc01ues1y.png" alt="Image inset-shadow" width="880" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Không có đường viền bên trong, sử dụng hình đại diện toàn màu trắng sẽ làm cho nó hòa trộn với nền gốc của nó. Điều tương tự cũng áp dụng cho chế độ tối. Đây là hình ảnh trực quan về những gì sẽ xảy ra có và không có đường viền bên trong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wa59gGAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7br9ok0wchp4u2auk1vl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wa59gGAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7br9ok0wchp4u2auk1vl.png" alt="Image inner-shadow-2" width="880" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Sử dụng thẻ div cho đường viền bên trong
&lt;/h5&gt;

&lt;p&gt;Đối với giải pháp này, một phần tử bổ sung (chính là thẻ div) được đặt hoàn toàn phía trên hình ảnh với độ mờ là 0,1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card__avatar"&amp;gt;
  &amp;lt;img src="assets/shadeed.jpg" alt="" /&amp;gt;
  &amp;lt;div class="border"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card__avatar {
  position: relative;
}

.card__avatar img {
  width: 56px;
  height: 56px;
  border-radius: 50%;
}

.border {
  position: absolute;
  width: 56px;
  height: 56px;
  border: 2px solid #000;
  border-radius: 50%;
  opacity: 0.1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Giải pháp này đúng, nhưng có một số hạn chế mà tôi sẽ giải thích sau đây.&lt;/p&gt;

&lt;h5&gt;
  
  
  Sử dụng thẻ svg
&lt;/h5&gt;

&lt;p&gt;Đối với giải pháp này, chúng tôi sẽ sử dụng một thẻ &lt;code&gt;svg&lt;/code&gt;. Ý tưởng là sử dụng mặt nạ hình tròn cho hình đại diện và phần tử &lt;code&gt;circle&lt;/code&gt; cho đường viền bên trong. SVG hoạt động tuyệt vời cho điều này.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg role="none" style="height: 56px; width: 56px"&amp;gt;
  &amp;lt;mask id="circle"&amp;gt;
    &amp;lt;circle cx="28" cy="28" fill="white" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
  &amp;lt;/mask&amp;gt;
  &amp;lt;g mask="url(#circle)"&amp;gt;
    &amp;lt;image
      x="0"
      y="0"
      height="100%"
      preserveAspectRatio="xMidYMid slice"
      width="100%"
      xlink:href="/assets/shadeed.jpg"
      style="height: 56px; width: 56px"
    &amp;gt;&amp;lt;/image&amp;gt;
    &amp;lt;circle class="border" cx="28" cy="28" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
  &amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.border {
  stroke-width: 3;
  stroke: rgba(0, 0, 0, 0.1);
  fill: none;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cả hai giải pháp đều hoạt động được khi chỉ xây dựng với ví dụ hình đại diện duy nhất. Tuy nhiên, mọi thứ bắt đầu trở nên thú vị hơn khi chúng ta thêm yếu tố trực tuyến.&lt;/p&gt;

&lt;h5&gt;
  
  
  Hình đại diện duy nhất có trạng thái trực tuyến
&lt;/h5&gt;

&lt;p&gt;Ở chế độ ánh sáng, hình tròn màu xanh lục có viền trắng. Tuy nhiên, ở chế độ tối, điều này nên được bị khỏi chính hình đại diện. Nói cách khác, nên sử dụng mặt nạ.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KhMVamqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ym1dpmrlfi8cdi8zwh9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KhMVamqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ym1dpmrlfi8cdi8zwh9v.png" alt="Image avatar-3" width="880" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Làm thế nào chúng ta có thể làm điều đó? Nếu chúng ta sử dụng giải pháp &lt;code&gt;svg&lt;/code&gt; cho hình đại diện duy nhất, điều này có thể được giải quyết dễ dàng bằng cách sử dụng mặt nạ SVG.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg role="none" style="height: 56px; width: 56px"&amp;gt;
  &amp;lt;mask id="circle"&amp;gt;
    &amp;lt;!-- [1] --&amp;gt;
    &amp;lt;circle cx="28" cy="28" fill="white" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
    &amp;lt;!-- [2] --&amp;gt;
    &amp;lt;circle cx="48" cy="48" fill="black" r="7"&amp;gt;&amp;lt;/circle&amp;gt;
  &amp;lt;/mask&amp;gt;
  &amp;lt;!-- [3] --&amp;gt;
  &amp;lt;g mask="url(#circle)"&amp;gt;
    &amp;lt;image
      x="0"
      y="0"
      height="100%"
      preserveAspectRatio="xMidYMid slice"
      width="100%"
      xlink:href="/assets/shadeed.jpg"
      style="height: 56px; width: 56px"
    &amp;gt;&amp;lt;/image&amp;gt;
    &amp;lt;circle class="border" cx="28" cy="28" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
  &amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hãy để tôi chia nhỏ đoạn code SVG trên:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Một vòng tròn để che hình đại diện thực tế.&lt;/li&gt;
&lt;li&gt;Một hình tròn nhỏ để cắt từ góc dưới bên phải của hình đại diện.&lt;/li&gt;
&lt;li&gt;Một group chứa &lt;code&gt;image&lt;/code&gt; và &lt;code&gt;circle&lt;/code&gt; cho đường viền bên trong trong suốt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dưới đây là hình ảnh giải thích cách hoạt động: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oRt7npDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atyciqkje2gt6ukfolrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oRt7npDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atyciqkje2gt6ukfolrf.png" alt="Image avatar-4" width="880" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cùng với đó, đây là đoạn code HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card__avatar"&amp;gt;
  &amp;lt;svg role="none" style="height: 56px; width: 56px"&amp;gt;
    &amp;lt;mask id="circle"&amp;gt;
      &amp;lt;circle cx="28" cy="28" fill="white" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
      &amp;lt;circle cx="48" cy="48" fill="black" r="7"&amp;gt;&amp;lt;/circle&amp;gt;
    &amp;lt;/mask&amp;gt;
    &amp;lt;g mask="url(#circle)"&amp;gt;
      &amp;lt;image
        x="0"
        y="0"
        height="100%"
        preserveAspectRatio="xMidYMid slice"
        width="100%"
        xlink:href="/assets/shadeed.jpg"
        style="height: 56px; width: 56px"
      &amp;gt;&amp;lt;/image&amp;gt;
      &amp;lt;circle class="border" cx="28" cy="28" r="28"&amp;gt;&amp;lt;/circle&amp;gt;
    &amp;lt;/g&amp;gt;
  &amp;lt;/svg&amp;gt;
  &amp;lt;div class="badge"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card__avatar {
  position: relative;
  display: flex;
  margin-right: 12px;
}

.badge {
  position: absolute;
  right: 3px;
  bottom: 3px;
  width: 10px;
  height: 10px;
  background: #5ad539;
  border-radius: 50%;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Khi một component như thế này cần phải thích ứng với cả bố cục sáng và tối, bạn nên sử dụng các biến CSS để xử lý nhằm lưu trữ các giá trị của màu cần thay đổi.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root {
  --primary-text: #050505;
  --secondary-text: #65676b;
  --bg-color: #fff;
}

html.is-dark {
  --primary-text: #e4e6eb;
  --secondary-text: #b0b3b8;
  --bg-color: #242526;
}

.card {
  background-color: var(--bg-color);
}

.card__title {
  color: var(--primary-text);
}

.card__subtitle {
  color: var(--secondary-text);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hết phần 2
&lt;/h3&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>component</category>
      <category>react</category>
    </item>
    <item>
      <title>Nghệ thuật dựng component trong thực tế-Phần 1</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Tue, 10 May 2022 16:07:58 +0000</pubDate>
      <link>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-1-3m5g</link>
      <guid>https://forem.com/buiminh15/nghe-thuat-dung-component-trong-thuc-te-phan-1-3m5g</guid>
      <description>&lt;p&gt;Bài viết được dịch từ: &lt;br&gt;
&lt;a href="https://ishadeed.com/article/building-real-life-components/"&gt;https://ishadeed.com/article/building-real-life-components/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dễ dàng đánh giá một component và triển khai trong HTML và CSS. Tôi đồng ý, thật sự dễ dàng khi bạn chỉ làm cho mục đích thực hành, nhưng đối với một dự án thực, điều đó hoàn toàn khác. Component mà bạn vừa xây dựng sẽ nhanh chóng bị lỗi trong trường hợp nó được sử dụng cho một dự án thực với nội dung thực. Tại sao? Đó là bởi vì không bao quát được tất cả các khía cạnh khi xây component.&lt;/p&gt;

&lt;p&gt;Trong bài viết này, tôi sẽ giới thiệu cho các bạn một component trông có vẻ đơn giản ngay từ cái nhìn đầu tiên, nhưng đằng sau nó là vô số công việc. Để thực tế hơn, tôi sẽ lấy một ví dụ từ Facebook Messenger.&lt;/p&gt;
&lt;h3&gt;
  
  
  Giới thiệu
&lt;/h3&gt;

&lt;p&gt;Đối với bài viết này, tôi sẽ lấy một component rất đơn giản từ Facebook Messenger. Xem hình bên dưới:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lLSRRLVE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ieb6wiyorx60gfty7b5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lLSRRLVE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ieb6wiyorx60gfty7b5.png" alt="Intro" width="880" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trong sidebar, có một CardList cho những người mà tôi đã nhắn tin trên Facebook. Trong bài viết này, tôi chỉ quan tâm đến component &lt;code&gt;Card&lt;/code&gt;. Bạn sẽ triển khai điều này như thế nào trong HTML &amp;amp; CSS? Thật đơn giản đúng không? Rằng nó bao gồm một hình ảnh và một thẻ &lt;code&gt;div&lt;/code&gt; bên cạnh nó. Đây là điều đầu tiên bạn có thể nghĩ đến.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BLPfwK4Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w77chq14nm99w36tgfvn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLPfwK4Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w77chq14nm99w36tgfvn.png" alt="Intro-2" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Có thể làm theo như trên nếu chỉ dành cho mục đích học tập. Tuy nhiên, nếu bạn muốn xây dựng một thứ gì đó vững chắc và linh hoạt, nó có thể thất bại nhanh chóng. Hãy cùng khám phá cách cơ bản để triển khai điều này trong HTML &amp;amp; CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card"&amp;gt;
  &amp;lt;img class="card__image" src="assets/shadeed.jpg" alt="" /&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h3&amp;gt;Ahmad Shadeed&amp;lt;/h3&amp;gt;
    &amp;lt;p&amp;gt;You: Thanks, sounds good! . 8hr&amp;lt;/p&amp;gt;
    &amp;lt;img class="card__seen" src="assets/shadeed.jpg" alt="" /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card {
  position: relative;
  display: flex; /* [1] */
  align-items: center; /* [2] */
  background-color: #fff;
  padding: 8px;
  border-radius: 7px;
  box-shadow: 0 3px 15px 0 rgba(0, 0, 0, 0.05);
}

.card h3 {
  font-size: 15px;
}

.card p {
  font-size: 13px;
  color: #65676b;
}

.card__image {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  margin-right: 12px;
}

.card__seen {
  position: absolute; /* [3] */
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  border-radius: 50%;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tôi đã đánh dấu một số dòng ở trên và muốn giải thích chúng một chút:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tôi đã sử dụng flexbox vì phù hợp với thiết kế.&lt;/li&gt;
&lt;li&gt;Các mục con cần được căn giữa theo chiều dọc.&lt;/li&gt;
&lt;li&gt;Seen sign được đặt hoàn toàn ở bên phải và căn giữa theo chiều dọc.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Hãy để component lỗi
&lt;/h4&gt;

&lt;p&gt;Việc triển khai ở trên không có gì sai, nhưng nó không thể mở rộng. Tôi sẽ hiển thị một biến thể khác cho component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RWUxrTGp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alilg2sw9bgan061x7rt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RWUxrTGp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alilg2sw9bgan061x7rt.png" alt="Intro-3" width="880" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hình tròn màu xanh ở bên phải cho biết rằng đây là một tin nhắn mới mà tôi chưa mở. Trong khi màu xanh lục trên hình đại diện cho biết người dùng hiện đang trực tuyến.&lt;/p&gt;

&lt;p&gt;Lưu ý cách chúng ta có hai hình tròn trên. Cách tốt nhất để thêm chúng là gì? Nếu bạn tham khảo CSS tôi đã viết cho thành phần ban đầu, bạn sẽ nhận thấy rằng chúng ta có lớp &lt;code&gt;.card__seen&lt;/code&gt; cho hình đại diện người dùng nhỏ ở bên phải. Trong biến thể này, &lt;code&gt;.card__seen&lt;/code&gt; nên được thay thế bằng hình tròn màu xanh lam.&lt;/p&gt;

&lt;p&gt;Với HTML &amp;amp; CSS được viết, việc triển khai biến thể này sẽ không thể thực hiện được cho đến khi chúng ta thay đổi HTML.&lt;/p&gt;

&lt;p&gt;Nói rõ hơn thì, biến thể trên chỉ là một phần rất nhỏ. &lt;strong&gt;Component này thực ra rất nhiều biến thể và trường hợp khác nữa.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Tất cả các biến thể
&lt;/h4&gt;

&lt;p&gt;Đây là hình ảnh trực quan cho các biến thể của component này.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YF6EcN_O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0mvxbtdigsy2g9aeq3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YF6EcN_O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0mvxbtdigsy2g9aeq3r.png" alt="variations-1" width="880" height="939"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Không chỉ vậy, chúng ta cũng cần style cho dark mode.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ze1wknno--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nog8ovcx9cq5wuqn7ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ze1wknno--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nog8ovcx9cq5wuqn7ck.png" alt="variations-2" width="880" height="939"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trong bài viết này, tôi sẽ cùng bạn khám phá cách tốt nhất để triển khai một component vững chắc có thể xử lý tất cả các biến thể và thay đổi mà nó không bị hỏng.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Spacing (khoảng trống)
&lt;/h4&gt;

&lt;p&gt;Trước khi làm bất cứ điều gì khác, tôi đã xem xét cẩn thận khoảng cách giữa mỗi phần tử UI và liệt kê ra những con số sau. Lưu ý rằng có rất nhiều khoảng cách và kích thước trong component đơn giản này.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tR9FagJD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i98r3n6js3dj91dstye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tR9FagJD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i98r3n6js3dj91dstye.png" alt="spacing" width="880" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Khi thiết kế giao diện người dùng và triển khai nó trong HTML &amp;amp; CSS, một trong những &lt;strong&gt;điều quan trọng cần quan tâm là khoảng cách&lt;/strong&gt;. Đánh giá thấp điều đó có thể dẫn đến giao diện người dùng sai khác theo thời gian.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hết phần 1
&lt;/h3&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>component</category>
      <category>react</category>
    </item>
    <item>
      <title>Dependency arrays trong React?</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Tue, 10 May 2022 13:30:21 +0000</pubDate>
      <link>https://forem.com/buiminh15/dependency-arrays-trong-react-1b3i</link>
      <guid>https://forem.com/buiminh15/dependency-arrays-trong-react-1b3i</guid>
      <description>&lt;p&gt;Bài viết được dịch từ:&lt;br&gt;
&lt;a href="https://devtrium.com/posts/dependency-arrays"&gt;https://devtrium.com/posts/dependency-arrays&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependency Array là gì?
&lt;/h3&gt;

&lt;p&gt;Dependency arrays được dùng với React hook&lt;/p&gt;

&lt;p&gt;Một số hook, như useEffect và useCallback có 2 đối số. Đối số đầu tiên là callback và cái thứ hai là dependency array. Nó có dạng một mảng các biến.&lt;/p&gt;

&lt;p&gt;Trong ví dụ sau, [counter] là dependency array của hook useEffect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log('Counter has value: ', counter);
}, [counter]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Những Reac hook có dependency array là:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;useEffect&lt;/li&gt;
&lt;li&gt;useLayoutEffect&lt;/li&gt;
&lt;li&gt;useCallback&lt;/li&gt;
&lt;li&gt;useMemo&lt;/li&gt;
&lt;li&gt;useImperativeHandle (hầu như không dùng)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dependency array (Mảng phụ thuộc) được sử dụng để làm gì?
&lt;/h3&gt;

&lt;p&gt;Mảng phụ thuộc về cơ bản cho hook biết "chỉ kích hoạt khi mảng phụ thuộc thay đổi". Trong ví dụ trên, nó có nghĩa là "chạy callback mỗi khi biến &lt;code&gt;counter&lt;/code&gt; thay đổi".&lt;/p&gt;

&lt;p&gt;Nếu bạn có nhiều phần tử trong một mảng phụ thuộc, hook sẽ kích hoạt nếu bất kỳ phần tử nào của mảng phụ thuộc thay đổi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  // chỉ chạy nếu `counter1` hoặc `counter2` thay đổi
  console.log('Either counter1 or counter2 changed (or both');
}, [counter1, counter2]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bạn có thể hỏi, nghĩa là gì khi hook "kích hoạt" mỗi khi một phần tử của mảng phụ thuộc thay đổi?&lt;/p&gt;

&lt;p&gt;Điều đó phụ thuộc vào hook. Đối với hook useEffect, nó có nghĩa là chạy callback. Đối với hook useCallback, nó có nghĩa là thay đổi hàm được trả về bởi hook. Tương tự cho useMemo, là trả về giá trị.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mảng phụ thuộc rỗng
&lt;/h4&gt;

&lt;p&gt;Như tôi đã nói, mảng phụ thuộc điều khiển khi hook kích hoạt. Vậy điều gì sẽ xảy ra khi mảng phụ thuộc rỗng?&lt;/p&gt;

&lt;p&gt;Đơn giản có nghĩa là hook sẽ chỉ kích hoạt một lần khi component được render lần đầu tiên. Vì vậy, đối với useEffect, nó có nghĩa là callback sẽ chạy một lần duy nhất trong vòng đời của component và không bao giờ chạy nữa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log('I will run only once');
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Đây là một pattern rất phổ biến khi bạn muốn làm điều gì đó ở đầu vòng đời của component, chẳng hạn như thực hiện việc lấy data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  // chỉ chạy lần đầu tiên khi được mount vào DOM lần đầu
  fetch('https://yourapi.com');
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/flamboyant-shannon-ckieqz"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Mình có đoạn code mẫu ở trên để làm rõ ý của tác giả. Ở trong đoạn code trên có button update lại state. Khi state thay đổi thì sẽ render lại nhưng các bạn nhìn console.log thì chỉ có 1 lần render và lý do là mảng phụ thuộc là rỗng. Các bạn có thể bỏ mảng phụ thuộc để test thêm để thấy được sự khác nhau.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nên cho gì vào mảng phụ thuộc?
&lt;/h3&gt;

&lt;p&gt;Quy tắc khá là đơn giản, một số ngoại lệ sẽ làm quy tắc khó hơn một chút.&lt;/p&gt;

&lt;p&gt;Quy tắc là: nếu bất kỳ &lt;strong&gt;biến nào được sử dụng bên trong hook nhưng được định nghĩa bên ngoài nó, thì nó sẽ nằm trong mảng phụ thuộc&lt;/strong&gt;. Điều đó đúng với cả biến cũng như hàm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';

const ExampleComponent = () =&amp;gt; {
  const width = 200;

  const printToConsole = (value) =&amp;gt; {
    console.log(value);
  };

  useEffect(() =&amp;gt; {
    printToConsole(width);
  }, [width, printToConsole]);

  return &amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHÚ Ý
Ví dụ trên thực sự sẽ dẫn đến lỗi, 
vì hàm printToConsole không được bao bọc trong useCallback. 
Điều đó sẽ dẫn đến việc kích hoạt useEffect trên 
mỗi lần render của ExampleComponent! 
Tôi sẽ chỉ ra một cách tốt hơn để làm điều này 
trong phần tiếp theo.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Như bạn có thể thấy trong ví dụ trên, cả biến &lt;code&gt;width&lt;/code&gt; và hàm &lt;code&gt;printToConsole&lt;/code&gt; đều được sử dụng trong hook &lt;code&gt;useEffect&lt;/code&gt;, và do đó cần phải cho vào trong mảng.&lt;/p&gt;

&lt;p&gt;Vì vậy, quy tắc khá là đơn giản, nhưng như tôi đã nói, có một số trường hợp ngoại lệ.&lt;/p&gt;

&lt;h4&gt;
  
  
  Biến được định nghĩa ngoài component
&lt;/h4&gt;

&lt;p&gt;Nếu một giá trị được xác định bên ngoài một component, thì giá trị đó sẽ được cố định và sẽ không thay đổi khi ứng dụng đang chạy. Vì vậy, React không cần bạn thêm nó vào mảng phụ thuộc.&lt;br&gt;
(Giờ thì mình mới hiểu cách khai báo biến khi dùng styled-component. Bạn nào dùng styled-component thì nhớ điều trên nhé 🥰)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';

const width = 200;

const printToConsole = (value) =&amp;gt; {
  console.log(value);
};

const ExampleComponent = () =&amp;gt; {
  useEffect(() =&amp;gt; {
    printToConsole(width);
  }, []);

  return &amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sẽ là tốt hơn khi đặt mọi thứ có thể bên ngoài một component. các biến (như &lt;code&gt;width&lt;/code&gt;) và các hàm tiện ích (như &lt;code&gt;printToConsole&lt;/code&gt;) không nhất thiết là cần định nghĩa bên trong component.&lt;/p&gt;

&lt;h4&gt;
  
  
  Những hàm đã được tối ưu hóa rồi
&lt;/h4&gt;

&lt;p&gt;Như chúng ta đã thấy, mục tiêu của mảng phụ thuộc là làm cho hook kích hoạt khi một trong các giá trị thay đổi. Không có ích gì khi đặt vào đó những thứ mà không thay đổi.&lt;/p&gt;

&lt;p&gt;Và có một số giá trị mà React biết chắc chắn sẽ không thay đổi, bởi vì chính React đảm bảo điều đó. Một ví dụ về hành vi này là hàm setter được trả về bởi một hook useState:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [counter, setCounter] = useState(0);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hàm &lt;code&gt;setCounter&lt;/code&gt; được React tối ưu hóa và sẽ không thay đổi. Vì vậy, ngay cả khi nó được sử dụng trong một hook với một mảng phụ thuộc, bạn không cần phải thêm nó vào mảng phụ thuộc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from 'react';

const ExampleComponent = () =&amp;gt; {
  const [counter, setCounter] = useState(0);

  useEffect(() =&amp;gt; {
    setCounter(10);
  }, []);

  return &amp;lt;p&amp;gt;Counter is: {counter}&amp;lt;/p&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Điều này cũng đúng với hàm &lt;code&gt;dispatch&lt;/code&gt; được trả về bởi hook &lt;code&gt;useReducer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHÚ Ý

Nếu `setCounter` được truyền vào như một props từ HOC, 
bạn phải đưa nó vào mảng phụ thuộc vì 
React không biết nó đến từ đâu. 
Mặc dù vậy, nó sẽ không kích hoạt hook, 
vì vậy sẽ an toàn khi làm như vậy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Refs
&lt;/h4&gt;

&lt;p&gt;Refs khá khó khăn để hiểu, và có lẽ cần một bài viết riêng về Refs.&lt;/p&gt;

&lt;p&gt;Nhưng liên quan đến mảng phụ thuộc, &lt;strong&gt;hãy lưu ý rằng việc đặt một ref vào một mảng phụ thuộc là vô ích&lt;/strong&gt;. Không đi quá nhiều vào chi tiết, bởi vì giá trị thay đổi của ref sẽ không kích hoạt việc component re-render, vì vậy hook sẽ không kích hoạt, bất kể mảng phụ thuộc của nó là gì (mảng phụ thuộc chỉ được kiểm tra khi component re-render).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHÚ Ý
Mặc dù việc đặt ref vào mảng phụ thuộc là vô ích, 
nhưng đừng đặt `ref.current` bên trong mảng phụ thuộc! 
Điều này sẽ dẫn đến lỗi!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sử dụng es-lint để giúp bạn
&lt;/h4&gt;

&lt;p&gt;Có rất nhiều trường hợp ngoại lệ, rất khó để nhớ hết. Nhưng đừng lo, ESLint luôn sẵn sàng trợ giúp bạn (Bạn đang sử dụng linter đúng không? Nếu không, bạn thực sự nên làm như vậy!).&lt;/p&gt;

&lt;p&gt;Quy tắc &lt;code&gt;react-hooks / expustive-deps&lt;/code&gt; sẽ cảnh báo bạn khi bạn đang làm sai với mảng phụ thuộc của mình. Nếu bạn muốn biết thêm thông tin, bạn có thể xem &lt;a href="https://reactjs.org/docs/hooks-rules.html#eslint-plugin"&gt;tài liệu chính thức của React!&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Cẩn thận với những gì bạn đặt trong mảng phụ thuộc
&lt;/h4&gt;

&lt;p&gt;Khi có sự thay đổi trong mảng phụ thuộc có nghĩa là hook sẽ được kích hoạt, bạn phải cẩn thận với những gì bạn đưa vào mảng phụ thuộc của mình. &lt;strong&gt;Đặc biệt, các hàm được định nghĩa bên trong component phải được bọc bằng &lt;code&gt;useCallback&lt;/code&gt; và các giá trị bọc bằng &lt;code&gt;useMemo&lt;/code&gt;!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Khi nào dùng useMemo và useCallback - Phần 3</title>
      <dc:creator>mikebui</dc:creator>
      <pubDate>Tue, 10 May 2022 08:41:26 +0000</pubDate>
      <link>https://forem.com/buiminh15/khi-nao-dung-usememo-va-usecallback-phan-3-475o</link>
      <guid>https://forem.com/buiminh15/khi-nao-dung-usememo-va-usecallback-phan-3-475o</guid>
      <description>&lt;p&gt;Bài dịch từ trang:&lt;br&gt;
&lt;a href="https://kentcdodds.com/blog/usememo-and-usecallback"&gt;https://kentcdodds.com/blog/usememo-and-usecallback&lt;/a&gt;&lt;br&gt;
của tác giả Kent C. Dodds.&lt;/p&gt;
&lt;h6&gt;
  
  
  React.memo (và những người bạn)
&lt;/h6&gt;

&lt;p&gt;Xem đoạn code sau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function CountButton({onClick, count}) {
  return &amp;lt;button onClick={onClick}&amp;gt;{count}&amp;lt;/button&amp;gt;
}

function DualCounter() {
  const [count1, setCount1] = React.useState(0)
  const increment1 = () =&amp;gt; setCount1(c =&amp;gt; c + 1)

  const [count2, setCount2] = React.useState(0)
  const increment2 = () =&amp;gt; setCount2(c =&amp;gt; c + 1)

  return (
    &amp;lt;&amp;gt;
      &amp;lt;CountButton count={count1} onClick={increment1} /&amp;gt;
      &amp;lt;CountButton count={count2} onClick={increment2} /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mỗi khi bạn click vào một trong các button, state của DualCounter sẽ thay đổi và do đó sẽ re-render, và re-render lại luôn cả 2 button CountButtons. &lt;/p&gt;

&lt;p&gt;Tuy nhiên, button thực sự cần render lại là button đã được click có phải không? Vì vậy, nếu bạn click vào button đầu tiên, cái thứ hai sẽ được re-render, nhưng không có gì thay đổi. Chúng tôi gọi đây là một "re-render không cần thiết."&lt;/p&gt;

&lt;p&gt;BẠN KHÔNG NÊN TỐI ƯU HÓA CÁC RE-RENDER KHÔNG CẦN THIẾT. &lt;/p&gt;

&lt;p&gt;React RẤT nhanh và tôi nghĩ rằng có rất nhiều thứ để bạn làm với thời gian của mình hơn là tối ưu hóa những thứ như thế này. Trên thực tế, nhu cầu tối ưu hóa với những gì tôi sắp cho bạn thấy là rất hiếm đến mức tôi thực sự chưa bao giờ cần phải làm điều đó trong 3 năm tôi làm việc trên các sản phẩm PayPal.&lt;/p&gt;

&lt;p&gt;Tuy nhiên, có những tình huống khi việc render có thể mất một lượng thời gian đáng kể (hãy nghĩ đến Đồ thị / Biểu đồ / Hoạt ảnh / v.v.) có tính tương tác cao. Nhờ bản chất thực dụng của React, thế nên có 1 cách giải quyết:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CountButton = React.memo(function CountButton({onClick, count}) {
  return &amp;lt;button onClick={onClick}&amp;gt;{count}&amp;lt;/button&amp;gt;
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bây giờ React sẽ chỉ re-render CountButton khi props của CountButton thay đổi! Nhưng chúng ta vẫn chưa xong. Hãy nhớ tới bình đẳng tham chiếu? Trong component của DualCounter, chúng ta đang định nghĩa các hàm increment1 và increment2 trong function của component (chính là function DualCounter()) , có nghĩa là mỗi khi DualCounter được re-render, các hàm đó sẽ là mới và do đó React sẽ re-render cả hai CountButtons.&lt;/p&gt;

&lt;p&gt;Vì vậy, đây là một tình huống khác mà useCallback và useMemo thực sự có ích:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CountButton = React.memo(function CountButton({onClick, count}) {
  return &amp;lt;button onClick={onClick}&amp;gt;{count}&amp;lt;/button&amp;gt;
})

function DualCounter() {
  const [count1, setCount1] = React.useState(0)
  // đoạn này
  const increment1 = React.useCallback(() =&amp;gt; setCount1(c =&amp;gt; c + 1), [])

  const [count2, setCount2] = React.useState(0)
  // đoạn này
  const increment2 = React.useCallback(() =&amp;gt; setCount2(c =&amp;gt; c + 1), [])

  return (
    &amp;lt;&amp;gt;
      &amp;lt;CountButton count={count1} onClick={increment1} /&amp;gt;
      &amp;lt;CountButton count={count2} onClick={increment2} /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bây giờ chúng ta có thể tránh được cái gọi là "re-render không cần thiết" của CountButton.&lt;/p&gt;

&lt;p&gt;Tôi muốn nhắc lại rằng tôi &lt;strong&gt;thực sự khuyên bạn không nên sử dụng React.memo (hoặc là PureComponent và shouldComponentUpdate) mà không có sự tính toán&lt;/strong&gt; bởi vì những tối ưu hóa đó đi kèm với chi phí và bạn cần đảm bảo rằng bạn biết chi phí đó sẽ không đáng kể so với lợi ích bạn nhận được (điều này khó xảy ra :D)&lt;/p&gt;

&lt;h4&gt;
  
  
  Tính toán phức tạp
&lt;/h4&gt;

&lt;p&gt;Đây là lý do khác mà useMemo là một hook tích hợp cho React (lưu ý rằng cái này không áp dụng cho useCallback). Lợi ích của useMemo là bạn có thể nhận một giá trị như:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a = {b: props.b}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thay đổi như sau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a = React.useMemo(() =&amp;gt; ({b: props.b}), [props.b])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Điều này không thực sự hữu ích cho trường hợp ở trên, nhưng hãy tưởng tượng rằng bạn có một hàm tính toán đồng bộ một giá trị mà việc tính toán rất mất thời gian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function RenderPrimes({iterations, multiplier}) {
  const primes = calculatePrimes(iterations, multiplier)
  return &amp;lt;div&amp;gt;Primes! {primes}&amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Điều đó có thể khá chậm với &lt;code&gt;iterations&lt;/code&gt; hoặc &lt;code&gt;multiplier&lt;/code&gt;. Bạn không thể làm cho phần cứng của người dùng nhanh hơn. Nhưng bạn có thể để &lt;strong&gt;function RenderPrimes&lt;/strong&gt; không bao giờ phải tính cùng một giá trị hai lần liên tiếp, đó là những gì useMemo sẽ làm cho bạn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function RenderPrimes({iterations, multiplier}) {
  const primes = React.useMemo(
    () =&amp;gt; calculatePrimes(iterations, multiplier),
    [iterations, multiplier],
  )
  return &amp;lt;div&amp;gt;Primes! {primes}&amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Cần xem xét kĩ giữa chi phí và lợi ích nhận được khi sử dụng việc tối ưu hóa.&lt;/p&gt;

&lt;p&gt;P.S Có thể nói việc tối ưu hóa đang là trend khi công ty nào cũng phỏng vấn điều này. Nhưng bạn có thực sự biết cách sử dụng nó.&lt;/p&gt;

&lt;p&gt;Dự án mình làm 80% các function con đều bọc useMemo hoặc useCallback (của người khác)và mình là người duy nhất không sử dụng bất kì useMemo hay useCallback trong đoạn code của mình. Đừng theo trend khi bạn chưa hiểu cách sử dụng.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
