React là một thư viện JavaScript để xây dựng giao diện người dùng, còn Angular là một framework hoàn chỉnh để xây dựng ứng dụng web. Với React, bạn viết component dưới dạng hàm trả về JSX và chọn các công cụ riêng cho định tuyến, form và dữ liệu; với Angular, bạn viết class TypeScript cùng template HTML và có sẵn định tuyến, form, HTTP client và dependency injection. Đây là cùng một bộ đếm ở cả hai.
Phiên bản Angular của component đó:
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<button (click)="increment()">Clicked {{ count() }} times</button>
`,
})
export class CounterComponent {
count = signal(0);
increment() {
this.count.update((n) => n + 1);
}
}
Các ý tưởng tương ứng một đối một: useState(0) của React là signal(0) của Angular, onClick={...} là (click)="...", và {count} là {{ count() }}. Khác biệt nằm ở chỗ code được đặt: một hàm trả về markup trong React, một class cùng chuỗi template trong Angular.
Thư viện và framework
Đây là khác biệt dẫn đến phần lớn các khác biệt còn lại. React lo phần render và state của component. Mọi thứ khác là do bạn chọn:
- Định tuyến: React Router, TanStack Router, hoặc định tuyến theo tệp của một framework.
- Lấy dữ liệu:
fetchtrong một effect, TanStack Query, hoặc loader và server component của một framework. - Form: ô nhập có kiểm soát thông thường, form action của React 19, hoặc React Hook Form.
- State toàn cục: context, Zustand, Redux Toolkit, Jotai.
Nhiều đội bỏ qua phần lớn các lựa chọn đó bằng cách bắt đầu từ một framework React như Next.js hoặc React Router ở chế độ framework, vốn đã gói sẵn định tuyến, tải dữ liệu và render phía máy chủ.
Angular đưa ra những lựa chọn đó thay bạn: @angular/router, form reactive và form dựa trên template, HttpClient, dependency injection, cấu hình kiểm thử và CLI ng để tạo component và service. Mọi dự án Angular nhìn chung đều giống nhau, đó là lý do phổ biến khiến các tổ chức lớn chọn nó. Cái giá phải trả là nhiều thứ phải học hơn và ít tự do thay thế từng phần hơn.
JSX và template
Component React trả về JSX, và JSX chính là JavaScript. Điều kiện dùng && hoặc toán tử ba ngôi, danh sách dùng .map(), và mọi thứ bạn làm được trong JavaScript đều làm được trong markup. Template của Angular là HTML với cú pháp riêng: @if, @for cùng track, binding [property], binding (event) và nội suy {{ }}. Template giữ markup và logic tách biệt rõ ràng; JSX đặt chúng ở cùng một chỗ và cho bạn toàn bộ ngôn ngữ. Đây là một danh sách có bộ lọc, tính năng thứ hai để so sánh.
Gõ an vào ô nhập và theo dõi console: toàn bộ hàm chạy lại ở mỗi lần gõ phím, và visible chỉ đơn giản được tính lại. Cùng component đó trong Angular, với template nằm trong tệp riêng:
import { Component, computed, signal } from '@angular/core';
@Component({
selector: 'app-fruit-filter',
templateUrl: './fruit-filter.component.html',
})
export class FruitFilterComponent {
fruits = ['Apple', 'Banana', 'Cherry', 'Grape', 'Mango', 'Peach'];
query = signal('');
visible = computed(() =>
this.fruits.filter((f) => f.toLowerCase().includes(this.query().toLowerCase()))
);
}
<input #box [value]="query()" (input)="query.set(box.value)" placeholder="Filter fruit" />
<ul>
@for (fruit of visible(); track fruit) {
<li>{{ fruit }}</li>
} @empty {
<li>No match</li>
}
</ul>
Trong Angular, computed khai báo rằng visible phụ thuộc vào query, nên Angular biết template nào đọc nó và chỉ tính lại visible khi query thay đổi. Trong React không có khai báo nào: component chạy lại và tính lại. key={fruit} trong React và track fruit trong Angular làm cùng một việc, cho framework biết mục nào trong danh sách là mục nào.
Ưu tiên JavaScript và ưu tiên TypeScript
React là JavaScript thuần cùng JSX, còn TypeScript là tùy chọn bạn thêm vào (npm create vite@latest my-app -- --template react-ts). Phần lớn dự án React mới đều thêm nó, nhưng bạn có thể học React mà không cần biết về kiểu. Angular được xây dựng cho TypeScript: decorator, dependency injection và bộ kiểm tra kiểu của template đều mặc định có nó. Nếu đội của bạn đã quen viết code có kiểu thì đây không phải vấn đề; nếu bạn mới học lập trình, đó là thêm một thứ phải học cùng lúc. Trang React với TypeScript cho thấy cách khai báo kiểu ở phía React.
Luồng dữ liệu và phát hiện thay đổi
Cả hai đều truyền dữ liệu xuống qua input (props trong React, input() hoặc @Input() trong Angular) và gửi sự kiện lên qua callback (hàm truyền qua props trong React, output() hoặc @Output() trong Angular). Khác biệt là cách mỗi bên nhận ra một thay đổi.
React xem state là các bản chụp bất biến. Bạn gọi setter với một giá trị mới, React chạy lại hàm component, so sánh JSX mới với JSX cũ rồi vá DOM. Không có gì được theo dõi tự động: chính hàm render là đồ thị dependency. Cách này dễ suy luận, và cái giá là đôi khi bạn phải thêm memo, useMemo hoặc useCallback (hoặc để React Compiler thêm giúp) để bỏ qua công việc.
Angular trước đây dùng Zone.js để phát hiện mọi sự kiện bất đồng bộ rồi kiểm tra cây component tìm binding đã thay đổi. Angular hiện đại đang chuyển sang signal: signal, computed và effect theo dõi giá trị nào được mỗi template đọc, nên Angular chỉ kiểm tra những component có signal thay đổi, và các phiên bản gần đây có thể chạy hoàn toàn không cần Zone.js. Template của Angular không chạy lại cả một hàm ở mỗi lần thay đổi như component React.
Trong code hằng ngày, hai bên gần nhau hơn so với cơ chế bên dưới: bạn giữ state, suy ra giá trị từ nó, và màn hình đi theo.
Quản lý state
Trong React, state cục bộ là useState hoặc useReducer, state dùng chung được đưa lên component cha hoặc đặt trong context, và state toàn ứng dụng thường nằm trong một thư viện store nhỏ. Trong Angular, state cục bộ là các signal trên component, còn state dùng chung thường nằm trong một service được inject vào bất cứ đâu cần; dependency injection là câu trả lời có sẵn của Angular cho câu hỏi "hai component cách xa nhau chia sẻ dữ liệu thế nào". NgRx dành cho các đội muốn một store kiểu Redux. React không có hệ thống dependency injection; context đảm nhận vai trò tương tự.
Bảng so sánh
| React | Angular | |
|---|---|---|
| Bản chất | Thư viện giao diện | Framework ứng dụng đầy đủ |
| Ngôn ngữ | JavaScript hoặc TypeScript | TypeScript |
| Markup | JSX bên trong JavaScript | Template HTML với cú pháp Angular |
| Dạng component | Hàm trả về JSX | Class có decorator và template |
| State cục bộ | useState, useReducer | Signal (signal, computed) |
| Cách cập nhật diễn ra | Component chạy lại, React so sánh kết quả | Signal và cơ chế phát hiện thay đổi cập nhật binding |
| State dùng chung | Props, context, một thư viện store | Service được inject, signal, NgRx |
| Định tuyến | Thư viện riêng hoặc framework | Có sẵn (@angular/router) |
| Form | Tùy bạn chọn, cùng form action của React 19 | Có sẵn (form reactive và form template) |
| HTTP | fetch hoặc một thư viện | Có sẵn (HttpClient) |
| Dependency injection | Không có (context là gần nhất) | Có sẵn |
| Công cụ | Vite hoặc CLI của một framework | Angular CLI (ng) |
| Render phía máy chủ | Next.js, React Router ở chế độ framework | Angular SSR |
| Ứng dụng di động | React Native | Ionic với Capacitor, NativeScript |
| Đơn vị duy trì | Meta và cộng đồng |
Độ khó khi học
React giúp bắt đầu nhanh hơn. Người mới đã biết JavaScript có thể làm ra một thứ thực tế sau khi học component, props, state và effect, và trang React là gì trình bày toàn bộ ý tưởng chỉ trong vài phút. Phần học được dời về sau: bạn phải chọn router, cách lấy dữ liệu và cách xử lý form, và mỗi codebase React lại chọn khác nhau.
Angular có khởi đầu dốc hơn: TypeScript, decorator, template, signal, dependency injection, module router và form, cùng RxJS cho một số API. Nhưng khi đã nắm được, mọi dự án Angular đều dùng cùng các thành phần theo cùng một cách, nên chuyển giữa các dự án dễ hơn.
Khi nào chọn bên nào
Chọn React khi:
- Bạn muốn một lõi nhỏ và tự do chọn phần còn lại, hoặc muốn một framework như Next.js cho render phía máy chủ và định tuyến theo tệp.
- Bạn dự định làm cả ứng dụng di động, nơi React Native dùng lại cùng mô hình component.
- Đội của bạn chủ yếu quen với JavaScript, hoặc bạn đang học lập trình front-end và muốn con đường ngắn nhất để có một ứng dụng chạy được.
Chọn Angular khi:
- Một đội lớn cần một cấu trúc chuẩn chung cho nhiều dự án, với ít quyết định kiến trúc phải tranh luận hơn.
- Bạn muốn form, HTTP, định tuyến và dependency injection được một đội duy trì cùng nhau và được CLI nâng cấp cùng lúc.
- Đội của bạn đã viết TypeScript và thích service dựa trên class cùng sự tách biệt rõ ràng giữa template và logic.
Cả hai đều đã trưởng thành, được dùng rộng rãi trong production và đều tốt cho sự nghiệp. Kỹ năng dùng lại được: component, luồng dữ liệu một chiều, state suy ra và cập nhật reactive là cùng những ý tưởng ở cả hai bên.
Câu hỏi thường gặp
React hay Angular tốt hơn?
Không bên nào tốt hơn tuyệt đối. Angular cho bạn một bộ công cụ hoàn chỉnh với nhiều quy ước sẵn, phù hợp với các đội lớn muốn có cùng một cấu trúc ở mọi dự án. React cho bạn một lõi nhỏ và tự do chọn phần còn lại, phù hợp với các đội muốn sự linh hoạt hoặc muốn dùng một framework như Next.js.
React có dễ học hơn Angular không?
Thường là có, ở giai đoạn đầu. Lõi của React gồm component, props, state và một vài hook, tất cả đều bằng JavaScript. Angular yêu cầu bạn học TypeScript, decorator, template, dependency injection, signal và module cho form và HTTP trước khi xây dựng được nhiều thứ. Bù lại, về sau Angular cần ít quyết định hơn.
Angular là framework còn React là thư viện phải không?
Đúng vậy. Angular cung cấp định tuyến, form, HTTP client, dependency injection, cấu hình kiểm thử và một CLI trong cùng một framework. React chỉ render giao diện; định tuyến, lấy dữ liệu và form đến từ các thư viện riêng hoặc từ một framework React như Next.js hay React Router.
Angular dùng TypeScript còn React dùng JavaScript phải không?
Angular được viết cho TypeScript và bộ công cụ của nó mặc định bạn dùng TypeScript. React hoạt động tốt như nhau với JavaScript thuần và TypeScript; phần lớn dự án React mới chọn TypeScript, nhưng đó là tùy chọn.
Có thể chuyển từ Angular sang React không?
Có, các khái niệm đều dùng lại được: component, input (props), output (props là callback) và state reactive. Những điều chỉnh chính là dùng JSX thay cho template, hook thay cho thành viên của class, và tự chọn thư viện cho định tuyến và form.