Tìm hiểu cách Jordan Walke tạo React và giới thiệu component tái sử dụng, UI khai báo và render theo state—đã định hình lại kiến trúc frontend hiện đại.

Jordan Walke là một kỹ sư phần mềm nổi tiếng vì đã tạo ra React khi làm việc tại Facebook. Trước React, frontend thường được xây quanh các trang, template và một đống “mã keo” cố gắng giữ HTML, CSS và JavaScript đồng bộ. Ý tưởng then chốt của Walke là đảo ngược mô hình: thay vì coi UI như tập hợp tài liệu bạn vá dần, hãy coi nó như một cây các component nhỏ, có thể tái sử dụng, ghép lại thành các tính năng lớn hơn.
Đây không chỉ là một thư viện mới—mà là một cách tư duy mới về công việc UI. Một component gom một phần giao diện cùng logic và state nó cần, rồi phơi ra một giao diện sạch (props) cho phần còn lại của app. Điều đó khiến xây UI giống việc lắp các viên Lego hơn là chỉnh sửa một trang mong manh.
React đã tạo sự khác biệt vì nó giúp các đội:
Chúng ta sẽ đi qua các ý tưởng thực tiễn đã làm React có ảnh hưởng:
Bạn không cần là chuyên gia framework để theo dõi. Mục tiêu là làm rõ mô hình tư duy—để bạn nhận ra các pattern React tốt, tránh hiểu nhầm phổ biến và áp dụng cùng nguyên tắc ngay cả ngoài React.
Trước React, nhiều đội xây giao diện phong phú bằng cách ghép template, thao tác DOM theo style jQuery và một đống quy tắc “khi X xảy ra, cập nhật Y”. Cách đó hoạt động—cho đến khi UI trở nên phức tạp.
Một mô hình phổ biến là: lấy dữ liệu, render HTML, rồi gắn handler sự kiện để thay đổi DOM trực tiếp. Khi state thay đổi (một mục mới, lỗi validation, một toggle), ai đó phải nhớ mọi chỗ phụ thuộc vào nó.
Điều đó dẫn tới lỗi như:
Khi màn hình phát triển, cùng quy tắc nghiệp vụ kết thúc ở nhiều handler khác nhau: “vô hiệu hóa nút nếu trường rỗng”, “đánh dấu mục chưa đọc”, “hiện trạng rỗng nếu không có kết quả”. Khi yêu cầu thay đổi, bạn phải lùng trong các file không liên quan để cập nhật từng bản sao.
Dữ liệu có thể mô hình hóa bằng vài cấu trúc rõ ràng: danh sách bài viết, đối tượng user, tập bộ lọc. UI, tuy nhiên, thêm các tổ hợp: loading vs loaded, error vs success, read vs unread, editing vs viewing, filtered vs unfiltered—thường xuất hiện cùng lúc.
Hãy tưởng tượng một news feed:
Nếu không có quy tắc có thể dự đoán như “UI là một hàm của state”, bạn sẽ phải phối nhiều thao tác DOM có thể xung đột. Mục tiêu của React là làm cho cập nhật đáng tin cậy: thay đổi dữ liệu/state, và UI re-render để khớp—mỗi lần.
Một component là một phần nhỏ của giao diện mà bạn có thể đặt tên, tái sử dụng và lý giải riêng. Nói đơn giản: một component nhận đầu vào, và trả về giao diện nên trông như thế nào cho những đầu vào đó.
Cách “đầu vào → đầu ra” này là cốt lõi của mô hình component. Thay vì coi một màn hình như một template lớn, bạn chia nó thành các khối mục đích—button, card, menu, form, và cả các phần lớn—rồi lắp chúng lại.
Trong React, đầu vào phổ biến nhất là props (viết tắt của “properties”). Props là giá trị bạn truyền vào component để cấu hình nó: văn bản, số, cờ, handler sự kiện, hoặc thậm chí UI khác.
Đầu ra là UI component render. Nếu props thay đổi, component có thể tạo đầu ra khác—mà không cần bạn phải tìm chỗ nào để cập nhật DOM.
Ví dụ, một component Button có thể nhận props như label, disabled và onClick. UserCard có thể nhận name, avatarUrl và status. Bạn có thể đọc giao diện component (props) giống như đọc đặc tả sản phẩm: “UI này cần gì để render đúng?”
Chia UI thành component đem lại lợi ích nhanh:
Modal, Input hay Dropdown có thể xuất hiện ở nhiều trang.Đây là bước chuyển lớn so với việc sao chép và chỉnh sửa markup theo từng trang. Components làm cho việc nhân bản trở nên thừa thãi—và cuối cùng không thể chấp nhận được.
React khuyến khích thiết kế UI giống như thiết kế hệ thống: như các phần có thể ghép. Một “Checkout page” trở thành cây component—CheckoutPage chứa OrderSummary, ShippingForm, và PaymentMethod. Mỗi phần có đầu vào rõ ràng và nhiệm vụ rõ ràng.
Sự thay đổi này—nghĩ trước tiên theo component—là lý do lớn khiến React thay đổi kiến trúc frontend. Nó cho các đội một đơn vị chung để thiết kế và phát triển: component.
Bước chuyển tư duy lớn nhất của React là UI khai báo: bạn mô tả giao diện nên trông như thế nào cho một trạng thái nhất định, và React lo việc cập nhật trang khi trạng thái đó thay đổi.
Thay vì tìm phần tử, sửa text, bật/tắt class và giữ DOM đồng bộ, bạn tập trung vào “hình dạng” của UI. Khi dữ liệu thay đổi, UI được mô tả lại, và React tìm ra tập các thay đổi tối thiểu cần thiết.
JSX là cách tiện để viết cấu trúc component bằng cú pháp trông giống HTML trong JavaScript. Nó không phải một ngôn ngữ templating mới phải học từ đầu; nó là viết tắt cho “component này render cây phần tử này”.
Lợi ích chính là markup và logic quyết định hiển thị sống cùng nhau, giúp component dễ hiểu khi nhìn riêng lẻ.
Mã mệnh lệnh tập trung vào cách cập nhật UI từng bước:
// Imperative: manually keep the DOM in sync
function setLoggedIn(isLoggedIn) {
const el = document.querySelector('#status');
el.textContent = isLoggedIn ? 'Welcome back' : 'Please sign in';
el.classList.toggle('ok', isLoggedIn);
el.classList.toggle('warn', !isLoggedIn);
}
Mã khai báo tập trung vào giao diện nên trông như thế nào cho trạng thái hiện tại:
function Status({ isLoggedIn }) {
return (
\u003cp className={isLoggedIn ? 'ok' : 'warn'}\u003e
{isLoggedIn ? 'Welcome back' : 'Please sign in'}
\u003c/p\u003e
);
}
Vì việc render được diễn đạt như một mô tả thuần, các component thường dễ đọc hơn, dễ review hơn và đơn giản để refactor. Designers, các kỹ sư quan tâm sản phẩm và thành viên mới thường có thể đọc JSX mà không phải lùng trong handler sự kiện và thao tác DOM.
Sự rõ ràng này cải thiện hợp tác: quyết định UI nằm ở một nơi, và thay đổi ít khi tạo ra tác dụng phụ ẩn ở nơi khác.
“State” đơn giản là dữ liệu có thể thay đổi theo thời gian khi người dùng tương tác với UI. Nó có thể là văn bản trong hộp tìm kiếm, một menu đang mở hay đóng, các mục trong giỏ hàng, hoặc kết quả một request mạng. Nếu nó có thể thay đổi và màn hình phải phản ánh sự thay đổi đó, thì đó là state.
Bước đi chủ chốt của React là coi render là hệ quả của state, không phải chuỗi các bước DOM thủ công. Bạn mô tả giao diện cho một state nhất định. Khi state cập nhật, React re-render những phần liên quan.
Mô hình tư duy này khác với “tìm phần tử, rồi cập nhật text, rồi toggle class.” Thay vào đó, bạn cập nhật state, và UI tự cập nhật bởi vì nó được dẫn xuất từ state.
Luồng dữ liệu một chiều có nghĩa là dữ liệu di chuyển theo một hướng duy nhất:
Điều này giảm bất ngờ vì bạn có thể theo đường cập nhật: có sự kiện, state thay đổi ở một chỗ, và UI re-render từ state mới. Ít có câu hỏi “ai thay đổi giá trị này?” hơn.
function Counter() {
const [count, setCount] = React.useState(0);
return (
\u003cdiv\u003e
\u003cp\u003eCount: {count}\u003c/p\u003e
\u003cbutton onClick={() =\u003e setCount(count + 1)}\u003eAdd\u003c/button\u003e
\u003c/div\u003e
);
}
Ở đây, count là state. Click button cập nhật state bằng setCount. React sau đó re-render, và đoạn văn hiển thị số mới. Bạn không bao giờ “sửa DOM” trực tiếp.
Cùng mẫu này mở rộng đến lọc danh sách (state = text bộ lọc, UI = các mục đã lọc) hoặc validation form (state = giá trị trường và lỗi, UI = thông báo). Dữ liệu thay đổi trước; view chỉ là kết quả.
Ý tưởng chính của React không phải là “vẽ lại trang nhanh hơn.” Mà là: hãy coi UI là kết quả của state, và khi state thay đổi, so sánh “những gì bạn muốn bây giờ” với “những gì bạn có trước kia”—rồi chỉ cập nhật phần thực sự thay đổi.
Khi state hoặc props của một component thay đổi, React gọi lại component để tạo một mô tả UI mới. Hãy tưởng tượng như chụp hai ảnh:
Thay vì xóa DOM và dựng lại, React cố tính toán tập các thao tác DOM nhỏ nhất cần thiết để chuyển từ A sang B.
“Virtual DOM” chỉ là đại diện UI trong bộ nhớ của React—một cây phần tử nhẹ mà mô tả những gì nên hiện trên màn hình. Nó không phải một trình duyệt thứ hai hay DOM nhanh hơn; nó là cấu trúc dữ liệu để React so sánh hiệu quả.
Reconciliation là quá trình tìm ra gì đã thay đổi giữa cây ảo trước và sau. React dùng một số heuristic để làm nhanh, ví dụ:
\u003cdiv\u003e không phải là \u003cspan\u003e).Khi React biết phần thay đổi, nó áp các cập nhật có mục tiêu lên DOM thực.
Đây không phải là ma thuật. Hiệu năng phụ thuộc vào cách dùng: key ổn định, tránh re-render không cần thiết, giữ công việc component nhỏ, và không làm tính toán nặng trong render. React có thể giảm xáo trộn DOM, nhưng cấu trúc component và luồng dữ liệu của bạn vẫn quyết định độ mượt của app.
Chiêu lớn để mở rộng của React không phải là một cờ tính năng hay addon—mà là composition: xây màn hình bằng cách lồng component, truyền data qua props và dùng children để component có thể bọc UI khác.
Khi đội tận dụng composition, họ ngừng nghĩ theo các trang một lần và bắt đầu nghĩ theo các phần nhỏ, tin cậy, có thể sắp xếp lại mà không cần viết lại mọi thứ.
childrenLồng là phiên bản trực quan của cấu trúc UI: trang chứa section, section chứa card, card chứa button. Props là núm điều chỉnh (text, state, callback). children là cách tạo component cung cấp cấu trúc trong khi cho phép người gọi quyết định nội dung bên trong.
Mô hình tốt: props tùy chỉnh, children lấp đầy, nesting lắp ráp.
Layout components định nghĩa cấu trúc và khoảng cách mà không nắm logic nghiệp vụ. Ví dụ: Page, SidebarLayout, Stack, Modal. Chúng thường dùng nhiều children để cùng một layout có thể bọc nhiều màn hình khác nhau.
Reusable inputs chuẩn hóa hành vi và kiểu form: TextField, Select, DatePicker. Thay vì sao chép labels, trạng thái lỗi và thông báo validation ở mọi nơi, bạn tập trung quyết định đó và phơi API props đơn giản.
List và item components giữ UI lặp lại ổn định. Một chia tách phổ biến là ItemList (fetching, phân trang, empty states) và ItemRow (một mục hiển thị như thế nào). Điều này giúp thay đổi render mà không phá vỡ xử lý dữ liệu.
Hooks là cách hiện đại để tái sử dụng hành vi có state (như toggle, state form, hay fetch) giữa các component mà không bắt chúng có cùng hình thức UI. Sự tách này giúp đội phát triển giao diện trong khi giữ logic nhất quán.
Composition là cách hệ thống thiết kế giữ được tính nhất quán: components trở thành khối “được duyệt”, layout định nghĩa quy tắc khoảng cách và thứ bậc. Khi hệ thống cập nhật—màu sắc, chữ, trạng thái tương tác—sản phẩm kế thừa cải tiến với ít chỉnh sửa thủ công hơn.
State chỉ là “dữ liệu có thể thay đổi”. Trong React, nơi đặt state quan trọng không kém bản thân state.
State cục bộ thuộc về một component duy nhất (hoặc widget nhỏ) và không cần đọc ở chỗ khác. Ví dụ: dropdown mở hay đóng, giá trị input hiện tại, tab đang chọn.
Giữ state cục bộ giảm phối hợp và giúp component dễ tái sử dụng. Quy tắc hay: nếu chỉ một component quan tâm, đừng đưa nó ra toàn app.
State chia sẻ là dữ liệu nhiều phần UI phải đồng ý. Ví dụ phổ biến:
Khi nhiều component cần cùng nguồn chân lý, nhân bản state dẫn đến lệch pha ("header nói 3 mục, trang giỏ hàng nói 2").
Lift state up: chuyển state lên cha chung gần nhất và truyền xuống qua props. Thường là lựa chọn đơn giản nhất và giữ luồng dữ liệu rõ ràng.
Context: hữu ích khi nhiều component cần cùng giá trị mà không muốn truyền props sâu (prop drilling), như theme hay auth. Context phù hợp với các quan tâm tương đối ổn định trên toàn app.
External stores: khi state phức tạp (cập nhật thường xuyên, dữ liệu dẫn xuất, workflow qua trang), một store chuyên dụng có thể tập trung logic và cập nhật.
Luồng dữ liệu một chiều của React phát huy khi có chủ rõ ràng cho mỗi phần state. Hãy nhắm tới một nguồn chân lý khi có thể, và suy ra phần còn lại (đếm, tổng, danh sách đã lọc) thay vì lưu trữ trùng lặp.
Lợi ích lớn nhất hàng ngày của React không phải một mẹo render tinh tế—mà là cách ranh giới component biến công việc UI thành các thay đổi nhỏ, an toàn hơn. Khi component có trách nhiệm rõ ràng và giao diện công khai ổn định (props), đội có thể refactor bên trong mà không buộc phải viết lại khắp app. Sự ổn định đó làm cho review dễ hơn, giảm phá vỡ vô tình và giúp thành viên mới hiểu nơi cần thay đổi.
Mô hình tư duy hữu ích: với props và state, component nên mô tả UI một cách có thể dự đoán. Dù hiệu ứng và API trình duyệt tồn tại, phần lớn logic component có thể giữ tính xác định. Đó là lý do testing React tập trung vào hành vi và kết quả:
Kiểm tra accessibility phù hợp tự nhiên: nếu test dùng roles và tên truy cập, bạn sẽ bắt nhầm labels thiếu, trạng thái focus hỏng và ngữ nghĩa không nhất quán sớm.
Khi component phơi ra API props nhỏ và che giấu chi tiết hiện thực, nhiều người có thể làm việc song song—một người chỉnh style, người khác thay fetch data, người thứ ba cập nhật test—mà ít va chạm.
Hiệu năng React thường ít liên quan tới “React chậm” và nhiều hơn tới lượng công việc bạn bắt trình duyệt làm. UI nhanh nhất là UI làm ít việc nhất: ít node DOM, ít layout/reflow, ít tính toán nặng, và ít lượt mạng.
Vấn đề thường gặp là re-render không cần thiết: một thay đổi nhỏ làm re-render một subtree lớn vì state đặt quá cao, hoặc props luôn có identity mới (objects/functions tạo inline mỗi lần).
Một vấn đề kinh điển khác là danh sách nặng—hàng trăm hoặc hàng nghìn hàng với ảnh, format và handler. Dù mỗi hàng “rẻ”, tổng công việc cộng lại và cuộn sẽ giật vì trình duyệt không bắt kịp.
Bắt đầu với cấu trúc:
Cũng hãy chú ý cảm nhận người dùng: giảm độ trễ input, tăng tốc first meaningful paint và giữ tương tác mượt. Cải thiện 20ms trong tương tác thường dùng có thể quan trọng hơn giảm 200ms trên màn hiếm.
Derived state là dữ liệu bạn có thể tính từ state/props khác (ví dụ fullName từ firstName + lastName, hoặc danh sách đã lọc từ một danh sách + query). Lưu nó thường tạo lỗi: bây giờ bạn có hai nguồn chân lý dễ lệch pha.
Ưu tiên tính các giá trị dẫn xuất trong render (hoặc memo nếu tốn kém). Chỉ lưu những gì không thể dẫn xuất—thường là input người dùng, phản hồi server và ý định UI (như “panel đang mở?”).
React không chỉ giới thiệu cách viết UI đẹp hơn; nó khuyến khích các đội tổ chức lại cách frontend được xây, chia sẻ và bảo trì. Trước khi component trở thành tư duy mặc định, nhiều dự án coi UI như các trang với script và template rải rác. Với React, đơn vị kiến trúc dần chuyển thành component: một mảnh UI với API rõ ràng (props) và hành vi có thể dự đoán.
React phù hợp với sự lên ngôi của single-page applications (SPA). Khi render được dẫn bởi state, “trang” ngừng là template phía server và bắt đầu là tổ hợp component + routing phía client. Chuyển này khiến mã được cấu trúc theo vùng tính năng và thành phần tái sử dụng hơn là các file HTML riêng.
Khi UI được dựng từ mảnh tái sử dụng, sẽ tự nhiên chuẩn hóa những mảnh đó. Nhiều tổ chức chuyển từ copy‑paste markup sang xây thư viện component: button, control form, modal, primitives layout và pattern như empty states. Dần dần, những thư viện này thường tiến hóa thành design system—component chia sẻ cộng với hướng dẫn—để các đội có thể ra trải nghiệm nhất quán mà không sáng tạo lại UI cho từng màn.
Components khuyến khích các đội đặt tên giống nhau. Khi mọi người nói về \u003cButton\u003e, \u003cTooltip\u003e hay \u003cCheckoutSummary\u003e, cuộc trao đổi trở nên cụ thể hơn: mọi người bàn về hành vi và ranh giới, không chỉ vẻ ngoài. Ngôn ngữ chung này cũng giúp người mới onboard nhanh hơn vì hệ thống có thể khám phá qua mã.
Thành công của React ảnh hưởng đến cách cộng đồng frontend nghĩ về UI: phát triển hướng component, render khai báo và luồng dữ liệu dự đoán trở thành kỳ vọng chung. Những framework khác cũng áp dụng ý tưởng tương tự, dù chi tiết triển khai khác, vì các thực hành này chứng tỏ dễ mở rộng trong đội thực tế.
React được biết đến vì làm cho UI phức tạp dễ tiến triển hơn, nhưng không miễn phí. Biết trước các đánh đổi giúp đội áp dụng đúng lý do—và tránh chạy theo phong trào.
React có đường cong học tập: components, hooks và mô hình tư duy như cập nhật state và effects cần thời gian để nắm. React hiện đại cũng giả định công cụ build (bundler, linting, thường TypeScript tuỳ chọn) làm tăng chi phí thiết lập và duy trì. Cuối cùng, React giới thiệu các lớp trừu tượng—thư viện component, routing, pattern fetch dữ liệu—có thể hữu ích nhưng cũng che giấu độ phức tạp đến khi có sự cố.
“React chỉ là phần view.” Về lý thuyết đúng; thực tế, React định hình kiến trúc. Ranh giới component, quyền sở hữu state và pattern composition ảnh hưởng đến luồng dữ liệu và cách đội tổ chức mã.
“Virtual DOM luôn nhanh hơn.” Virtual DOM chủ yếu về cập nhật có thể dự đoán và trải nghiệm dev. React có thể nhanh, nhưng hiệu năng phụ thuộc vào pattern render, memoization, kích thước danh sách và tránh re-render không cần thiết.
React phù hợp cho app có nhiều trạng thái tương tác, codebase tồn tại lâu và nhiều dev cùng làm. Với một trang marketing tĩnh hoặc vài widget nhỏ, các lựa chọn đơn giản hơn (template server-rendered, JS nhẹ, hoặc framework tối giản) có thể dễ triển khai và duy trì hơn.
Nếu bạn đang prototype một app React và muốn kiểm chứng các ý tưởng nhanh (ranh giới component, quyền sở hữu state, pattern composition), workflow vibe-coding có thể hữu ích. Ví dụ, Koder.ai cho phép bạn mô tả tính năng trong chat và sinh frontend React hoạt động cùng backend Go/PostgreSQL, sau đó lặp với snapshot/rollback và xuất mã nguồn khi sẵn sàng tiếp quản thủ công. Đây là cách thực tế để kiểm tra quyết định kiến trúc trên một tính năng thực trước khi cam kết toàn bộ xây dựng.
Tiếp theo: prototype một tính năng thực, đo lường độ phức tạp và vận tốc đội, rồi mở rộng các pattern một cách có chủ đích—không phải mặc định.
Jordan Walke đã tạo React khi làm việc tại Facebook. React quan trọng vì nó thay thế mã “keo” DOM thủ công và dễ vỡ bằng cách tiếp cận dựa trên component và điều khiển bởi state để xây dựng giao diện người dùng — giúp các giao diện phức tạp dễ mở rộng, gỡ lỗi và bảo trì hơn.
Các template thường phân tán quy tắc UI giữa markup và những trình xử lý sự kiện rải rác ("khi X xảy ra, cập nhật Y"). Components gói UI + logic đằng sau một giao diện nhỏ (props), nên bạn có thể ghép các tính năng từ những mảnh có thể dự đoán được thay vì vá trang theo thời gian.
Một component là một đơn vị có thể tái sử dụng, nhận đầu vào (thường là props) và trả về mô tả về giao diện cần hiển thị cho những đầu vào đó.
Trong thực tế, hướng tới:
Props là các đầu vào bạn truyền vào component để cấu hình nó (văn bản, cờ, callback, hoặc UI khác). Hãy coi props như một hợp đồng:
disabled, onSubmit) hơn các đối tượng mơ hồUI khai báo có nghĩa là bạn mô tả giao diện nên trông như thế nào cho trạng thái hiện tại, chứ không phải làm thế nào để cập nhật DOM từng bước.
Thực hành:
JSX là một cú pháp cho phép bạn viết cấu trúc UI trông giống HTML bên trong JavaScript. Nó hữu ích vì logic render và markup điều khiển nó sống cùng nhau, khiến component dễ đọc và review như một khối.
State là bất kỳ dữ liệu nào có thể thay đổi theo thời gian và ảnh hưởng đến những gì người dùng thấy (văn bản input, trạng thái loading, nội dung giỏ hàng, v.v.).
Quy tắc thực tế: lưu nguồn chân lý (input người dùng, phản hồi server, ý định UI), và suy ra các thứ khác (đếm, danh sách đã lọc) từ nó.
Luồng dữ liệu một chiều có nghĩa là:
Điều này giúp debug dễ hơn vì bạn có thể lần theo đường cập nhật: sự kiện → thay đổi state → re-render.
Virtual DOM là bản biểu diễn UI trong bộ nhớ của React. Khi state/props thay đổi, React so sánh mô tả UI trước và sau rồi chỉ cập nhật DOM thực nơi cần thiết.
Để tránh vấn đề thường gặp:
key ổn định cho các mục trong listBắt đầu đơn giản rồi mở rộng khi cần:
Ưu tiên một nguồn chân lý khi có thể và suy ra phần còn lại để tránh lệch pha.