React 19 là phiên bản lớn của React, phát hành vào tháng 12 năm 2024. Nó bổ sung Actions (các hàm async quản lý trạng thái chờ, lỗi và form), các hook useActionState, useOptimistic và use, ref như một prop thông thường, cùng các thẻ <title> và <meta> được React chuyển vào head của tài liệu. React 19.2 (tháng 10 năm 2025) thêm <Activity> và useEffectEvent.
Mọi ví dụ bên dưới đều chạy trên React 19.2. Đây là một Action: một hàm async được truyền cho form, với trạng thái chờ và lỗi trả về được useActionState xử lý.
Nhấn Save khi ô còn trống để xem lỗi, rồi gõ một cái tên và lưu: nút hiển thị "Saving..." trong 800 ms. Không có useState cho lỗi, không có cờ isLoading và không có e.preventDefault().
Actions và form action
Trong React 18, với mỗi form bạn đều viết cùng những bước: chặn submit mặc định, bật cờ loading, await request, lưu lỗi, tắt cờ. React 19 gọi một hàm làm việc async bên trong transition là một Action, và tự lo phần sổ sách đó cho bạn.
startTransition(vàuseTransition) giờ nhận một hàm async.isPendinggiữ giá trịtruecho đến khi cả hàm chạy xong.<form action={fn}>gọifnvớiFormDatacủa form khi form được submit. Nó chạy như một Action, và sau khi chạy xong React đặt lại các trường uncontrolled của form.<button formAction={fn}>cho một nút submit có action riêng.- useActionState giữ giá trị mà action trả về gần nhất, nên một action có thể trả về thông báo lỗi hoặc bản ghi đã lưu.
useFormStatustừreact-domcho phép một component bên trong form biết form đó có đang submit hay không, mà không cần truyền props xuống. Nó cần một<form>cha, nên ở đây nó xuất hiện trong một khối code tĩnh:
import { useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending } = useFormStatus();
return <button disabled={pending}>{pending ? 'Sending...' : 'Send'}</button>;
}
useOptimistic
useOptimistic hiển thị kết quả bạn mong đợi trong lúc Action vẫn đang chạy, và quay về state thật khi Action kết thúc. Một bộ đếm lượt thích có thể tăng ngay khi bạn nhấn, rồi giảm lại nếu request thất bại.
const [optimisticLikes, addOptimisticLike] = useOptimistic(likes, (current, delta) => current + delta);
Trang useOptimistic có một ví dụ chạy được với API giả cố tình thất bại, để bạn xem quá trình hoàn tác.
API use
use đọc giá trị từ một promise hoặc từ một context. Với promise, nó suspend component cho đến khi promise resolve, và trong lúc đó <Suspense> gần nhất hiển thị fallback. Khác với mọi hook khác, use có thể được gọi bên trong if hay vòng lặp, và sau một lệnh return sớm.
React 19 cũng cho phép bạn render trực tiếp <ThemeContext value="dark"> thay vì <ThemeContext.Provider>. Cả hai đều xuất hiện trong ví dụ này:
ref như một prop, và cleanup cho ref
Function component giờ nhận ref như mọi prop khác. Bạn không còn cần bọc nó trong forwardRef để chuyển một ref xuống DOM element.
Ref callback giờ cũng có thể trả về một hàm cleanup. React gọi hàm đó khi element rời khỏi màn hình, giống cách cleanup của effect hoạt động. Một callback không trả về gì vẫn được gọi với null khi bị gỡ bỏ, như trong React 18.
Nhấn nút vài lần và đọc console: mỗi lần gỡ bỏ ghi dòng cleanup, mỗi lần quay lại ghi attached to DIV.
Metadata cho tài liệu
Bạn có thể render <title>, <meta> và <link> ở bất kỳ đâu trong component, và React chuyển chúng vào <head>. Một component trang có thể tự đặt tiêu đề mà không cần thư viện như react-helmet.
Bản xem trước không có tab trình duyệt để hiển thị, nên effect ghi log document.title thay vào đó. Chuyển bài viết và tiêu đề được log thay đổi theo.
Stylesheet cũng được xử lý tương tự: <link rel="stylesheet" href="..." precedence="default" /> bên trong một component được chèn vào head đúng một lần, theo thứ tự precedence, và React chờ nó tải xong rồi mới hiển thị nội dung cần đến nó. Một <script async src="..."> được nhiều component render chỉ tải một lần. react-dom cũng export preload, preinit, preconnect và prefetchDNS để gợi ý tải tài nguyên.
Activity và useEffectEvent (React 19.2)
<Activity mode="hidden"> ẩn các phần tử con mà không vứt bỏ state của chúng. React ẩn DOM, chạy cleanup của các effect và khôi phục mọi thứ khi mode trở lại "visible". Nó hợp với các tab và panel mà bạn đoán người dùng sẽ quay lại.
Gõ một ghi chú, chuyển sang About rồi quay lại. Chữ vẫn còn đó, và console cho thấy effect đã được cleanup trong lúc bị ẩn. Thay wrapper <Activity> bằng {tab === 'notes' && <Notes />}, ghi chú sẽ mất mỗi lần chuyển tab.
useEffectEvent đưa một hàm ra khỏi danh sách dependency của effect. Hàm đó luôn thấy props và state mới nhất, nhưng việc chúng thay đổi không khiến effect chạy lại:
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => onConnected());
connection.connect();
return () => connection.disconnect();
}, [roomId]); // theme is not a dependency
}
19.2 cũng thêm cacheSignal cho Server Components (nó cho bạn biết khi nào kết quả của cache() không còn cần nữa) và Performance Tracks trong panel performance của Chrome DevTools. React 19.1 thêm captureOwnerStack, một hàm chỉ có trong môi trường development, trả về những component đã render component hiện tại.
Server Components và Server Functions
Server Components là những component chạy trước trên máy chủ (hoặc lúc build) và gửi kết quả đến trình duyệt. Chúng có thể là async và đọc trực tiếp cơ sở dữ liệu, và code của chúng không bao giờ được gửi xuống client. Server Functions (ban đầu gọi là Server Actions) là các hàm async được đánh dấu bằng 'use server' mà một client component có thể gọi như một hàm bình thường. Cả hai đều cần một framework có bundler hỗ trợ chúng, chẳng hạn Next.js App Router, nên chúng không chạy được trong trình soạn thảo này.
// A Server Component: async, runs on the server only
export default async function Notes() {
const notes = await db.notes.findMany();
return notes.map((note) => <Note key={note.id} note={note} />);
}
// A Server Function, usable as a form action
async function createNote(formData) {
'use server';
await db.notes.create({ text: formData.get('text') });
}
Các API bị loại bỏ và thay đổi
React 19 loại bỏ những API đã bị deprecate từ nhiều năm:
| Bị loại bỏ | Dùng thay thế |
|---|---|
ReactDOM.render, ReactDOM.hydrate | createRoot, hydrateRoot từ react-dom/client |
unmountComponentAtNode | root.unmount() |
findDOMNode | một ref trên DOM element |
String ref (ref="input") | useRef hoặc một ref callback |
Legacy context (contextTypes, getChildContext) | createContext với static contextType hoặc use |
Kiểm tra propTypes (giờ bị bỏ qua mà không báo gì) | TypeScript, hoặc tự viết kiểm tra |
defaultProps trên function component | giá trị mặc định của tham số |
react-dom/test-utils | act từ react; React Testing Library cho phần còn lại |
react-test-renderer/shallow | package react-shallow-renderer |
React.createFactory | JSX |
Class component vẫn giữ defaultProps. Lỗi cũng được báo theo cách khác: lỗi bị error boundary bắt được ghi bằng console.error một lần, lỗi không được bắt đi đến window.reportError, và createRoot nhận các tùy chọn onCaughtError và onUncaughtError để bạn tự báo lỗi.
Nâng cấp lên React 19
Hãy nâng cấp lên React 18.3 trước. Phiên bản này giống hệt 18.2 nhưng cảnh báo về các API đã bị deprecate và những thay đổi khác mà React 19 cần, để bạn sửa chúng trong lúc ứng dụng vẫn chạy. React 19 cũng yêu cầu JSX transform hiện đại, thứ mà Vite và mọi framework hiện nay đều đã dùng. Sau đó cài React 19:
npm install react@^19 react-dom@^19
npm install --save-dev @types/react@^19 @types/react-dom@^19
Hướng dẫn nâng cấp chính thức chỉ đến các codemod cho những thay đổi máy móc. Codemod đầu tiên xử lý string ref, lệnh import act và ReactDOM.render; codemod thứ hai cập nhật code TypeScript theo các kiểu mới:
npx codemod@latest react/19/migration-recipe
npx types-react-codemod@latest preset-19 ./src
Sau khi nâng cấp, không có gì buộc bạn phải dùng Actions hay các hook mới. Các component, hook và class component hiện có vẫn tiếp tục chạy; bạn có thể chuyển từng form sang <form action> một.
Câu hỏi thường gặp
React 19 được phát hành khi nào?
React 19 ra bản ổn định vào tháng 12 năm 2024. React 19.1 ra mắt vào tháng 3 năm 2025 và React 19.2 vào tháng 10 năm 2025.
React 19 có những thay đổi lớn nào?
Actions (các hàm async tự lo trạng thái chờ, lỗi và form cho bạn), các hook useActionState, useOptimistic và use, ref như một prop bình thường, <Context> dùng làm provider, cùng các thẻ <title> và <meta> được chuyển vào head của tài liệu. Server Components đã ổn định cho các framework.
forwardRef có bị deprecate trong React 19 không?
Function component giờ có thể nhận ref như một prop thông thường, nên code mới không cần forwardRef. Nó vẫn chạy được, và đội ngũ React cho biết nó sẽ bị deprecate trong một phiên bản tương lai.
React 19 có làm hỏng ứng dụng React 18 đang có không?
Chủ yếu qua các API đã bị loại bỏ: ReactDOM.render, findDOMNode, string ref, legacy context, propTypes và defaultProps trên function component. React 19 cũng yêu cầu JSX transform hiện đại. Hãy nâng cấp lên React 18.3 trước, sửa các cảnh báo deprecate của nó, rồi chạy các codemod của React 19.
Có cần Next.js để dùng React 19 không?
Không. Actions, các hook mới, ref như một prop và metadata đều chạy trong một ứng dụng client thuần dựng bằng Vite. Server Components và Server Functions cần một framework hỗ trợ chúng, chẳng hạn Next.js.