React 19
(github.com/facebook)19.0.0 (ngày 5 tháng 12 năm 2024)
Tính năng mới
React
- Actions:
startTransitiongiờ có thể chấp nhận các hàm bất đồng bộ. Các hàm này được gọi là "Actions", cập nhật trạng thái ở nền và commit UI trong một lần. Actions có thể thực hiện các side effect như yêu cầu bất đồng bộ, và sẽ chờ công việc hoàn tất trước khi Transition kết thúc. useActionState: Hook mới cho phép sắp xếp Actions trong Transition và truy cập trạng thái. Nhận trạng thái ban đầu và reducer.useOptimistic: Hook mới để cập nhật trạng thái trong khi Transition đang diễn ra. Khi Transition hoàn tất, trạng thái sẽ được cập nhật thành giá trị mới.use: API mới để đọc tài nguyên trong lúc render. Chấp nhận Promise hoặc Context; nếu cung cấp Promise, quá trình sẽ bị tạm dừng cho đến khi giá trị được resolve.- Dùng
refnhư một prop: Có thể dùng ref như một prop mà không cầnforwardRef. - Prewarming các sibling của Suspense: Khi component bị tạm dừng, React sẽ ngay lập tức commit phần fallback của ranh giới Suspense gần nhất.
React DOM client
- Prop
actioncủa<form>: Form Actions tự động quản lý form và tích hợp vớiuseFormStatus. Tự động reset form khi thành công. - Hỗ trợ metadata tài liệu: Có thể render native các thẻ metadata của tài liệu từ component.
- Hỗ trợ stylesheet: Chèn stylesheet vào
<head>của client trước khi hiển thị nội dung của ranh giới Suspense. - Hỗ trợ script bất đồng bộ: Có thể render script bất đồng bộ ở bất kỳ đâu trong cây component.
React DOM server
- Thêm API
prerendervàprerenderToNodeStream: API cho tạo site tĩnh, được thiết kế để hoạt động trong các môi trường streaming như Node.js stream và web stream.
React Server Components
- Tính năng RSC: Directive, server component và server function đã được ổn định. Các thư viện có chứa server component giờ có thể nhắm React 19 làm peer dependency.
Sắp bị loại bỏ
- Truy cập
element.ref: Loại bỏ việc truy cậpelement.ref, ưu tiênelement.props.ref. react-test-renderer: Trong React 19,react-test-renderersẽ ghi cảnh báo deprecation và chuyển sang concurrent rendering để dùng trên web.
Thay đổi lớn
React
- Bắt buộc dùng JSX transform mới: Cần JSX transform mới để cải thiện kích thước bundle và cho phép dùng JSX mà không cần import React.
- Lỗi render không bị throw lại: Nếu lỗi không bị Error Boundary bắt, nó sẽ được báo qua
window.reportError. - Loại bỏ
propTypes: Việc dùngpropTypessẽ bị bỏ qua một cách im lặng. Khuyến nghị chuyển sang TypeScript. - Loại bỏ
defaultPropscủa function: Có thể dùng tham số mặc định của ES6 thay thế. - Loại bỏ string refs: Cần migrate việc dùng string refs sang ref callback.
React DOM
- Loại bỏ
react-dom/test-utils:actđược chuyển từreact-dom/test-utilssang react. Các utility khác bị loại bỏ. - Loại bỏ
ReactDOM.render,ReactDOM.hydrate: Được thay thế bằngReactDOM.createRootvàReactDOM.hydrateRootcho concurrent rendering.
Những thay đổi đáng chú ý
React
- Dùng
<Context>làm provider: Có thể render<Context>làm provider thay cho<Context.Provider>. - Hỗ trợ custom element: React 19 vượt qua tất cả các bài kiểm tra custom element.
- Thay đổi trong StrictMode:
useMemovàuseCallbacksẽ tái sử dụng kết quả memoization của lần render đầu tiên.
React DOM
- Diff cho lỗi hydration: Khi xảy ra mismatch, React 19 sẽ ghi một lỗi duy nhất bao gồm phần khác biệt của nội dung không khớp.
Thay đổi về TypeScript
- Cấm implicit return: ref giờ chỉ chấp nhận cleanup function. Implicit return sẽ gây lỗi.
useRefcần đối số khởi tạo: Đối số khởi tạo giờ là bắt buộc.- Typing
ReactElementnghiêm ngặt hơn: props của React element giờ mặc định làunknownthay vìany.
1 bình luận
Ý kiến trên Hacker News
Tôi không hiểu lắm vì sao ở đây có nhiều người ghét React đến vậy
Tôi bắt đầu sự nghiệp với Laravel và JS thuần, nhưng sau khi dùng React, việc xây dựng các ứng dụng có khả năng mở rộng trở nên thực tế hơn và frontend cũng thú vị hơn
Dù chuyển công ty, React vẫn dễ bắt nhịp lại, và nhờ hỗ trợ TypeScript cùng hệ sinh thái lớn, tôi có cảm giác có thể xây dựng và mở rộng gần như mọi thứ khá dễ dàng
Tôi cũng không hiểu vì sao các tính năng mới lại làm mọi người sợ. Vẫn có thể làm SPA hoặc theo cách cũ, giống như khi NoSQL DB, Spring Boot hay Kotlin xuất hiện: nếu không muốn dùng thì không dùng
Tôi từng hiểu rằng Jetpack Compose và SwiftUI cũng lấy cảm hứng từ React; hình như tôi đã thấy trong tài liệu Android trước đây, nhưng giờ không tìm được nữa
Tuy nhiên tôi vẫn chưa có vài chục năm kinh nghiệm, nên không biết ngày xưa các nhóm lớn làm những web app lớn như Airbnb bằng jQuery hay JS thuần thì vui đến mức nào. Giờ đây tôi thậm chí khó tưởng tượng sẽ giải quyết quản lý trạng thái, thao tác DOM và side effect bằng JS thuần ra sao
Có lẽ một ngày nào đó tôi cũng sẽ phàn nàn về một framework mới và nói rằng React từng tốt biết bao
Lập luận thường là “frontend lúc nào cũng đuổi theo thứ mới mẻ hào nhoáng, và React cũng chỉ là một trong số đó”, nhưng React đã tồn tại từ năm 2013 và khoảng từ 2015 đã khá mainstream rồi
Họ cũng nói framework và thư viện làm tăng độ phức tạp, nhưng khi hỏi cụ thể là loại phức tạp nào thì gần như không nhận được câu trả lời. Nếu xây dựng một ứng dụng có ý nghĩa mà không dùng framework, cuối cùng bạn sẽ phát minh ra framework riêng thiếu khả năng quản lý, kiểm thử và tài liệu
Các bước compile và bundling cũng thường bị phàn nàn, nhưng giờ đã có những framework đã được kiểm chứng như Expo, Next.js, Meteor, nên gần như không còn lý do để tự viết cấu hình webpack hay build pipeline
Xu hướng nhét web framework vào mọi nơi trong 10 năm qua đã tạo ra hàng loạt site chậm và dễ hỏng, thường được thiết kế quá mức nhưng trải nghiệm người dùng lại chẳng khá hơn nhiều so với năm 2008
Với một số frontend developer, dù câu hỏi là gì thì câu trả lời cũng là một tổ hợp React / Node / Vite / Angular / Vue / Nuxt / Next / Bun / Deno / Svelte / SvelteKit, và nếu có thể thì nên chạy trên hàng chục swarm Docker do Kubernetes thống trị. Kiểu như: “Muốn đưa CV lên online à? Vậy trong 3 tuần tới hãy vẽ sơ đồ luồng trạng thái của app nhé”
Có vẻ React bị chửi nhiều hơn vì những người chạy theo trào lưu framework đã chuyển sang thứ hào nhoáng tiếp theo, còn những người vốn ghét các framework kiểu này thì vẫn tiếp tục ghét, nên giờ không còn ai ở lại bảo vệ mớ hỗn độn này nữa. Tôi nghĩ các framework còn lại rồi cũng sẽ chịu số phận tương tự theo thời gian
Cách hoạt động thực tế bị che giấu khá nhiều và không trực quan, dễ mắc lỗi, và cũng dễ viết ra UI hiệu năng kém
Bạn phải liên tục nghĩ xem thứ gì chạy bao nhiêu lần, phải đưa gì vào dependency array, phải đưa gì vào
useCallbackvàuseEffect, nên tải nhận thức rất lớnMột phần cộng đồng còn khuyến nghị cả những dependency React mà dự án không cần, chỉ làm tăng overhead và độ phức tạp
Business logic và UI logic cũng dễ bị trộn lẫn
Trong một thời gian, SPA có những nhược điểm so với MPA, nhưng nhờ các chuẩn web hiện đại và việc các SPA framework đưa vào server-side rendering, những vấn đề đó hiện nay gần như đã được giải quyết
https://www.youtube.com/watch?v=b2F-DItXtZs
Đây là một bản phát hành rất hay, nhưng cũng thấy hơi tội cho những người mới bước vào phát triển frontend lúc này
Những mô tả kiểu “một hook mới dùng để sắp xếp Action bên trong Transition, truy cập trạng thái action và trạng thái pending; nhận một reducer có thể gọi Action cùng trạng thái khởi tạo dùng cho lần render đầu tiên; và cũng nhận một chuỗi tùy chọn để hỗ trợ progressive enhancement cho form nếu được truyền vào prop form action” nghe thì tính năng có vẻ tốt, nhưng quá dài dòng
Nếu hôm nay bắt đầu làm website, có lẽ sẽ rất mông lung không biết nên bắt đầu từ đâu
Dù vậy React vẫn là một framework xuất sắc và bản phát hành này cũng là một cải tiến. Phê bình này không chỉ nhắm vào React mà gần như là toàn bộ mảng phát triển frontend
Dùng kiểu render phía máy chủ truyền thống với thứ như HTMX sẽ tốt hơn nhiều
Tôi đã kiếm tiền bằng phát triển frontend React trong 4 năm và làm website đầu tiên vào năm 2005; hiện đang chuyển một dự án client từ React sang HTMX và thấy tốt hơn hẳn
Ít bug hơn, ít bẫy do dùng hook sai hơn
Nếu cần render phía client thì tôi sẽ dùng Solid hoặc Vue, nhưng sẽ tránh React. Nếu không có lựa chọn thì chúc may mắn
Tiền đề cơ bản như binding một chiều, DOM ảo, re-render và tính diff về căn bản không thuyết phục được tôi. Tức là dùng gấp đôi bộ nhớ trình duyệt, rồi mỗi tương tác đều re-render toàn bộ và tính diff
Câu trả lời lúc đó là “trước tiên làm cho ổn định, rồi sau đó làm cho nhanh”, nhưng giờ thì đầy các cấu trúc kiểu hack để làm cho nhanh, mà lại chẳng nhanh cũng chẳng ổn định
Tôi cho rằng các framework binding hai chiều thẳng thắn ít nhất đảm bảo được tốc độ, còn độ ổn định đến từ kinh nghiệm. React thì chỉ đơn giản là rối rắm. Thấy tiếc cho những kỹ sư mà lần đầu bước vào frontend là React, vì có lẽ việc xóa bỏ và học lại còn khó hơn nhiều so với học mới
Từ góc nhìn của người đã đi qua VBScript, JS, jQuery, Mootools, Applets, ActionScript, YUI/Ext/Sencha, Backbone, Knockout, Angular 1, Angular 2, React, cho tới Vue 1, tôi muốn nói rằng hãy thử Flutter. Nó thật sự rất mới mẻ
Chỉ có điều Dart là vấn đề. Nếu Flutter là TypeScript thì đã gần với lý tưởng hơn một chút, nhưng Dart vẫn tiếp tục duy trì tinh thần churn bất tận của frontend
Các tiêu chuẩn web nói chung cũng ổn định hơn bao giờ hết. Các lập trình viên trẻ không cần học hàng trăm mẹo layout chỉ để trang hiển thị đúng trên nhiều trình duyệt, và đôi khi cũng ít cần hack chỉ để khớp với một trình duyệt hơn
Tôi hiểu cảm giác mệt mỏi vì JavaScript, nhưng tôi nghĩ hiện nay là một trong những thời điểm tốt nhất để học
Mọi thứ cảm giác giống phát triển đúng nghĩa thật sự, và so với tình hình trước đó thì như một luồng gió mới
Với 99% lập trình viên, trước khi app phát triển đến một mức nào đó thì sẽ không cần các tính năng như vậy, thậm chí có thể không bao giờ cần. React cũng không bắt buộc
Từng có thời tôi thích các framework phía client như React, nhưng cuối cùng nhận ra chúng đã thêm độ phức tạp vào mọi nơi có thể
Backend, frontend, stack DevOps, đâu đâu cũng có độ phức tạp, và để đồng bộ các phần phức tạp phân tán đó sẽ còn tiếp tục phải thêm nhiều lớp hơn nữa
Việc UI tự động render lại khi dữ liệu hoặc model thay đổi là hướng đi đúng
Cách làm chi tiết có thể tranh luận, nhưng mỗi khi dữ liệu thay đổi mà phải sửa UI trực tiếp theo kiểu mệnh lệnh thì rất khó trụ lâu xét về quy mô codebase hoặc đội ngũ
Nó chồng thêm độ phức tạp khổng lồ để bắt trình duyệt web render các hộp theo cách mà ban đầu chúng không được thiết kế cho việc đó, và dưới danh nghĩa thay đổi mô hình lập trình, nó cũng làm mất đi đáng kể năng suất và hệ công cụ
Có những ý tưởng và triển khai rất hay, nhưng tôi không chắc nó có đáng đến vậy không. Đôi khi tôi tự hỏi liệu đó có phải một kiểu cơ chế đảm bảo việc làm không
Đây không chỉ là vấn đề của ReactJS, toàn bộ hệ sinh thái JavaScript đã phát điên với thư viện và công cụ, nhưng riêng React đặc biệt khó chịu khi bắt đầu, đến mức cuối cùng create react app ra đời để có thể tạo một app hello world trong thời gian hợp lý
Tôi đã ngừng kỳ vọng mình sẽ hiểu lý do đổi API class component sang hook
Có thể chọn framework đơn giản hơn, cũng có thể tránh orchestration phía server
Nếu không có lựa chọn, cũng có thể tự bắt đầu một dự án mà bạn tin là với stack đơn giản hơn sẽ có lợi thế về hiệu quả
Một trong những phần hay nhất của bản phát hành này là có thể dùng ref như prop. Giờ không cần
forwardRefnữaBài viết blog dễ đọc hơn: https://react.dev/blog/2024/12/05/react-19
const error = await updateName(newName);, tôi không hiểu vì saoupdateNamelại trả về lỗiKhông thể cứ ném
Errornhư đúng kiểu JS/TS sao?Nếu trong 45 bình luận đến giờ, “redux” được nhắc tới 7 lần, thì ở đây tôi muốn nhắc đến Jotai như đại diện cho dòng Recoil. Có lẽ ngay cả với React 19, nó nhiều khả năng đã hoạt động mà không cần thay đổi riêng nào
Khi độ phức tạp của frontend đủ lớn, các công cụ quản lý trạng thái khác thường trở thành trở ngại hơn mức cần thiết
Nếu bạn đã bắt đầu ghét React, nhưng thật ra chỉ là mệt mỏi vì bức tường vô tận các hằng số action, việc luồn prop, cuộc chiến với provider/context lồng nhau, và việc chạy trốn sang pub-sub, thì những thứ như Jotai đáng để thử một lần
https://github.com/pmndrs/zustand
https://github.com/pmndrs/valtio
Jotai khiến tôi cảm thấy có quá nhiều boilerplate thủ công, còn Valtio thì có nhiều “phép màu” proxy, nên dù cá nhân tôi thích nhưng không chắc đó có phải lựa chọn tốt cho cả đội không
Zustand nằm ở giữa boilerplate và phép màu, nên tôi đã chọn nó cho một dự án lớn đang làm
Vài năm trước, khi bắt đầu làm ứng dụng React, mọi gói quản lý trạng thái tôi thấy đều đầy những thuật ngữ như thế, và bây giờ vẫn vậy
Cuối cùng, để thoát khỏi những thứ đó và tập trung vào công việc, tôi đã tự làm một giải pháp [1], và nó đang chạy tốt trong môi trường production. Tiếc là không có lựa chọn phổ biến nào hoạt động tương tự
[1] https://github.com/facepunch/react-class-model
Điểm hay của context hook là có thể composition, và khi kết hợp với các truy vấn được cache thì có thể tạo ra một pattern khá dễ bảo trì
Tôi tò mò Jotai mang lại cải thiện thực chất nào ở đây
Tôi thật sự hy vọng sẽ không bao giờ phải đụng tới redux hay sagas nữa
Tôi không thích phần lớn các tính năng mới được đưa vào
Actions và các hook
useActionState/useOptimistictrông như một cái bẫy độ phức tạp lớn. Hookusecó cái tên quá thiếu thông tin, và không xử lý promise được tạo bên trong componentChắc chắn là có lý do tốt nào đó, nhưng cách truyền promise qua prop rồi xử lý bằng hook
usecó vẻ sẽ tạo ra nhiều phức tạp hơn các workaround hiện tạiServer Components cũng trông khá phức tạp, và may là tôi vẫn chưa phải xử lý chúng
Việc cải thiện thông báo lỗi hydration là đáng hoan nghênh, còn các thay đổi dùng provider và dùng ref như prop là những cải tiến chất lượng tốt
Nhìn chung, nếu để làm SPA thì tôi thích React/Preact. Dùng cùng một thư viện component giàu tính năng như MUI và một giải pháp quản lý trạng thái đơn giản như Preact Signals khiến việc làm SPA khá trực quan
Tuy vậy, tôi lo độ phức tạp đang len lỏi vào từng chút một. Chỉ đọc phần mô tả các hook mới trong ghi chú phát hành thôi cũng đã thấy tải nhận thức lớn
Ngược lại, React Compiler là công cụ thật sự cần thiết. Nó sẽ giúp component bớt phức tạp hơn vì lập trình viên không cần tự viết các tối ưu hóa điển hình bên trong component
Tôi đang mong chờ bản phát hành và việc tích hợp với Vite, v.v.; theo tôi nghe được thì nó cũng dự kiến hỗ trợ Preact
Sẽ tốt hơn nếu API
useđược đổi sang một tên khác với tiền tố chung của hookNgười mới học React hooks chắc sẽ bối rối khi thấy
usecó thể được gọi có điều kiện, còn hooks thông thường thì khôngThật sự rất mừng vì họ đã trì hoãn bản phát hành để giải quyết vấn đề Suspense song song
Tôi chưa dùng thử, nhưng rất kỳ vọng; nhìn chung đây là một bản phát hành xuất sắc
Tin nóng: hỗ trợ đầy đủ custom elements. Tức là Web Components