Quay Lại Blog

Có Gì Mới Trong React 19: Góc Nhìn Của Frontend Developer

March 24, 20264 phút đọc
Thẻ:ReactReact 19FrontendJavaScript

React 19 Đã Đến — Và Nó Thay Đổi Tất Cả

Sau nhiều năm cập nhật dần dần, React 19 mang lại cảm giác như một bước nhảy thế hệ. Là người đã xây dựng với React hơn 3 năm, tôi có thể nói bản phát hành này thay đổi căn bản cách chúng ta suy nghĩ về data fetching, xử lý form, và kiến trúc server-client.

Hãy cùng điểm qua các tính năng quan trọng nhất trong dự án thực tế.

Actions: Không Cần Quản Lý Loading State Thủ Công

Trước React 19, mỗi lần submit form trông như thế này:

const [isPending, setIsPending] = useState(false);
const [error, setError] = useState(null);

async function handleSubmit() {
  setIsPending(true);
  setError(null);
  try {
    await submitData();
  } catch (e) {
    setError(e.message);
  } finally {
    setIsPending(false);
  }
}

Với Actions, React tự động xử lý pending states, errors, và optimistic updates:

function UpdateName() {
  const [error, submitAction, isPending] = useActionState(
    async (prev, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) return error;
      redirect("/profile");
      return null;
    },
    null
  );

  return (
    <form action={submitAction}>
      <input name="name" />
      <button disabled={isPending}>
        {isPending ? "Đang lưu..." : "Lưu"}
      </button>
      {error && <p>{error}</p>}
    </form>
  );
}

Điều này loại bỏ cả một loại code boilerplate. Trong các dự án của tôi, riêng tính năng này đã giảm ~40% code liên quan đến form.

useOptimistic: Phản Hồi UI Tức Thì

useOptimistic cho phép bạn hiển thị state lạc quan trong khi action đang xử lý:

function TodoList({ todos }) {
  const [optimisticTodos, addOptimistic] = useOptimistic(
    todos,
    (state, newTodo) => [...state, { ...newTodo, sending: true }]
  );

  async function addTodo(formData) {
    const todo = { text: formData.get("text") };
    addOptimistic(todo);
    await saveTodo(todo);
  }

  return (
    <>
      {optimisticTodos.map((todo) => (
        <div key={todo.id} style={{ opacity: todo.sending ? 0.5 : 1 }}>
          {todo.text}
        </div>
      ))}
      <form action={addTodo}>
        <input name="text" />
        <button>Thêm</button>
      </form>
    </>
  );
}

UI cập nhật ngay lập tức, và nếu server action thất bại, React tự động quay lại state trước đó.

use(): Hook Đọc Promise

API use() mới cho phép bạn đọc promise và context trực tiếp trong render:

function Comments({ commentsPromise }) {
  const comments = use(commentsPromise);

  return (
    <ul>
      {comments.map((c) => (
        <li key={c.id}>{c.text}</li>
      ))}
    </ul>
  );
}

Kết hợp với <Suspense>, tạo ra pattern data-fetching sạch sẽ không cần useEffect:

<Suspense fallback={<Spinner />}>
  <Comments commentsPromise={fetchComments()} />
</Suspense>

Không còn điệu nhảy useEffect + useState cho data fetching.

ref Là Prop

Một trong những pattern khó chịu nhất trong React là forwardRef. React 19 loại bỏ hoàn toàn:

// Trước (React 18)
const Input = forwardRef((props, ref) => {
  return <input ref={ref} {...props} />;
});

// Sau (React 19)
function Input({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

forwardRef giờ đã deprecated. Bớt một wrapper, component signatures sạch hơn.

Document Metadata Trong Components

Giờ bạn có thể render <title>, <meta>, và <link> trực tiếp trong bất kỳ component nào:

function BlogPost({ post }) {
  return (
    <article>
      <title>{post.title}</title>
      <meta name="description" content={post.description} />
      {post.content}
    </article>
  );
}

React tự động chuyển chúng lên <head>. Không cần react-helmet hay thư viện tương tự nữa.

Xử Lý Lỗi Cải Tiến

React 19 cung cấp thông báo lỗi tốt hơn và cách xử lý lỗi mới:

  • onCaughtError: Kích hoạt khi React bắt lỗi trong Error Boundary
  • onUncaughtError: Kích hoạt khi lỗi được throw và không được bắt bởi Error Boundary nào
  • onRecoverableError: Kích hoạt khi React tự động phục hồi từ lỗi

Kết Luận

React 19 không chỉ là một bản nâng cấp — đó là sự thay đổi paradigm hướng tới:

  1. Ít boilerplate hơn — Actions loại bỏ quản lý state thủ công cho các thao tác async
  2. UX tốt hơn mặc định — Optimistic updates và Suspense khiến app cảm giác nhanh tức thì
  3. API đơn giản hơnforwardRef biến mất, use() thay thế pattern useEffect, metadata trong components
  4. Tư duy server-first — Server Components và Server Actions là công dân hạng nhất

Nếu bạn bắt đầu dự án mới hôm nay, không có lý do gì để không dùng React 19. Với dự án hiện có, lộ trình migration mượt mà — hầu hết thay đổi là bổ sung, và đội React đã cung cấp codemods cho breaking changes.

Tương lai của React đã đến, và nó sạch hơn, nhanh hơn, trực quan hơn bao giờ hết.