Peeps Avatar

Hello, codestus.

Go back

Quản lý Form với useActionState và useFormStatus trong React

Published at: 12/06/2024

7 mins read

Làm việc với Form trong React, đặc biệt là khi xử lý các hành động trên server, thường có thể gặp khó khăn. Tuy nhiên, việc giới thiệu các hook useActionStateuseFormStatus trong React Canary (sắp được phát hành với React 19.0.0) hứa hẹn sẽ làm cho quy trình này trở nên hợp lý và có tổ chức hơn. Các hook này, đã được hỗ trợ trong Next.js, cung cấp một cách mạnh mẽ để quản lý trạng thái và hành động của Form một cách hiệu quả. Trong bài viết này, chúng ta sẽ tìm hiểu cách các hook này hoạt động và cách chúng có thể đơn giản hóa việc quản lý Form trong các ứng dụng React.

useActionState là gì?

Hook useActionState trong React được thiết kế để quản lý các hành động và trạng thái Form một cách hiệu quả. Nó hoạt động tương tự như các hook khác trong React, yêu cầu được gọi bên trong một functional component. Hook này nhận một hàm và trạng thái ban đầu làm tham số và trả về một mảng chứa trạng thái hiện tại, một hàm hành động để gọi hành động Form, và một boolean chỉ ra liệu hành động Form có đang chờ xử lý hay không.

Ví dụ Sử Dụng useActionState

Dưới đây là một ví dụ cơ bản để minh họa cách useActionState hoạt động:

'use client';

import { useActionState } from 'react';
import { action } from './action';

const Homepage = () => {
  const [state, formAction, isPending] = useActionState(action, {
    name: '',
    error: '',
    status: false,
  });

  console.log(state);

  return (
    <main>
      <form action={formAction}>
        <input type="text" name="name" />
        <button type="submit" disabled={isPending}>
          {isPending ? 'Loading...' : 'Submit'}
        </button>
      </form>
    </main>
  );
};

export default Homepage;

Trong ví dụ này, chúng ta có một Form đơn giản với một trường input[name] và một nút submit. Chúng ta sử dụng hook useActionState để quản lý trạng thái và hành động của Form. Hàm action là một hành động trên server mà chúng ta sẽ gọi khi Form được gửi.

Như bạn thấy, chúng ta truyền hàm action và trạng thái ban đầu vào hook useActionState. Nó trả về một mảng gồm trạng thái, hàm formActionisPending. Chúng ta có thể sử dụng trạng thái để hiển thị trạng thái Form và formAction để gọi hành động trên server. isPendingtrue khi Form đang gửi và false khi Form đã được gửi.

💡
Bạn có thể giữ bất kỳ trạng thái ban đầu nào, không nhất thiết phải giống như bài viết đang đề cập. Nhưng bạn phải trả về cùng trạng thái từ hàm action. Nếu không, bạn sẽ không thể nhận được trạng thái mới nhất như mong đợi.

Bây giờ hãy xem tệp action.ts trông như thế nào. Chúng ta phải giữ nó trong một file riêng vì component HomePage của chúng ta là một component phía client và chúng ta không thể gọi các hành động trên server trực tiếp từ phía client.

'use server';

export const action = async (prevState: any, formData: FormData) => {
  const name = formData.get('name') as string;

  /// Validate the name | bạn có thể sử dụng zod để xác thực
  if (!name || name.trim() === '') {
    return {
      name: '',
      error: 'Name is required',
      status: false,
    };
  }

  /// Lưu tên vào cơ sở dữ liệu
  console.log(name);

  return {
    name: '',
    error: '',
    status: true,
  };
};

Như bạn thấy, chúng ta xuất ra một hàm action nhận prevStateformData làm tham số. Chúng ta lấy tên từ formData và xác thực nó. Sau khi xác thực, chúng ta trả về trạng thái mới. Trạng thái này sẽ được cập nhật trong component HomePage. Trong trường hợp không có lỗi, bạn có thể thực hiện các thao tác mong muốn với dữ liệu và trả về trạng thái mới.

useFormStatus là gì?

Như tên gọi, useFormStatus là một hook để lấy trạng thái của Form. Khi chúng ta gửi Form, hook useFormStatus sẽ cung cấp cho chúng ta trạng thái của Form.

  • pending: Sẽ là true khi Form đang gửi và false khi Form đã được gửi.
  • data: Chúng ta có thể lấy dữ liệu của Form sau khi Form được gửi. data.get('name') sẽ cho chúng ta tên của Form.
  • method: Chúng ta có thể lấy phương thức của Form. Phương thức sẽ là POST trong trường hợp gửi Form.
  • action: Một tham chiếu đến hàm được truyền vào hành động.

Hook useFormStatus phải được gọi từ một component được render bên trong một Form. Và nó là trạng thái của Form cha.

Ví dụ Sử Dụng useFormStatus

// button.tsx

import { useFormStatus } from 'react-dom';

const Button = () => {
  const { pending } = useFormStatus();

  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Loading...' : 'Submit'}
    </button>
  );
};

export default Button;

Vì chúng ta đang sử dụng gửi Form, chúng ta có thể sử dụng hook useFormStatus để lấy trạng thái của Form. Thuộc tính pending sẽ là true khi Form đang gửi và false khi Form đã được gửi.

Bây giờ chúng ta có thể sử dụng component Button này trong component HomePage.

'use client';

import { useActionState } from 'react';
import { action } from './action';
import Button from './button';

const Homepage = () => {
  const [state, formAction] = useActionState(action, {
    name: '',
    error: '',
    status: false,
  });

  return (
    <main>
      <form action={formAction}>
        <input type="text" name="name" />
        <Button />
      </form>
    </main>
  );
};

export default Homepage;

Bây giờ chúng ta có một component button hiển thị trạng thái của Form. Nó sẽ hiển thị "Loading..." khi Form đang gửi và "Submit" khi Form đã được gửi.

Kết Luận

Các hook useActionStateuseFormStatus trong React sẽ làm cho cuộc sống của các nhà phát triển trở nên dễ dàng hơn khi làm việc với các Form sử dụng hành động trên server. Làm việc với Form có thể hơi phức tạp, và các hook này làm cho việc quản lý trạng thái và hành động của Form trở nên dễ dàng hơn. Các hành động trên server với sự gia tăng của RSC (React Server Component) đã trở nên quan trọng hơn và các hook này sẽ giúp chúng ta rất nhiều.

Hy vọng bài viết này giúp bạn hiểu rõ hơn về cách sử dụng các hook useActionStateuseFormStatus trong React

Tham khảo: https://reetesh.in