Data fetching trong thư viện Refine

4 min read

Dữ liệu là thành phần không thể thiếu trong bất kì ứng dụng hay trang web nào. Để quản lý dữ liệu, thư viện Refine cung cấp cho chúng ta một DataProvider – nó chịu trách nhiệm giao tiếp với các API và cung cấp dữ liệu bằng cách truyền các tham số liên quan đến tài nguyên. Refine cung cấp rất nhiều các cách khác nhau để làm điều này (useOneuseListuseUpdate).

1. Fetching

  • Giả sử cần lấy ra dữ liệu với id: 123 và từ endpoint “products”, chúng ta sẽ sử dụng hook useOne. Ở bên trong, nó gọi phương thức dataProvider.getOne từ data provider.
  • Dưới đây sẽ là cách thực hiện:
import React from "react";
import { useOne, BaseKey } from "@refinedev/core";

export const Product: React.FC = () => {
    const { data, error, isError, isLoading } = useOne<IProduct>({
        resource: "products",
        id: 123,
    });

    if (isError) <div>{error?.message}</div>;

    if (isLoading) <div>Loading...</div>;

    const product = data?.data;

    return (
        <div>
            <h4>{product?.name}</h4>
            <p>Material: {product?.material}</p>
            <p>Price {product?.price}</p>
        </div>
    );
};
  • Khi cần update một dữ liệu, ví dụ với id: 124 và endpoint: “products”, Chúng ta có thể dùng hook “useUPDATE”, dưới đây là ví dụ:
export const Product: React.FC = () => {
    const { data, error, isError, isLoading, isFetching } = useOne<IProduct>({
        resource: "products",
        id: 124,
    });

    const { mutate, isLoading: isUpdating } = useUpdate();

    if (isError) {
        return (
            <div>
                <h1>Error</h1>
                <pre>{JSON.stringify(error)}</pre>
            </div>
        );
    }

    if (isLoading)  return <div>Loading...</div>;

    const incrementPrice = async () => {
        await mutate({
            resource: "products",
            id: 124,
            values: {
                price: Math.random() * 100,
            },
        });
    };

    const product = data?.data;

    return (
        <div>
            <h4>{product?.name}</h4>
            <p>Material: {product?.material}</p>
            <p>Price {product?.price}</p>
            <button onClick={incrementPrice} disabled={isUpdating || isFetching}>Update Price</button>
        </div>
    );
};

Refine mang lại 1 bộ các hooks dành riêng cho việc CRUD rất đa dạng và tiện lợi:

2. Cách Refine quản lý dữ liệu và trạng thái

Refine sẽ sử dụng TanStack Query ở nền để quản lý các trạng thái và dự liệu. Nó cung cấp các loading, error, … để giúp người dùng dễ dàng làm việc hơn trong quá trình phát triển phần mềm.

Refine xử lý dữ liệu và trạng thái theo cách có cấu trúc và hiệu quả, cung cấp cho các nhà phát triển các công cụ mạnh mẽ để quản lý dữ liệu liền mạch trong ứng dụng. Sau đây là một số khía cạnh chính về cách Refine xử lý dữ liệu và trạng thái:

  • Phương pháp dựa trên tài nguyên: Tổ chức dữ liệu xung quanh các tài nguyên, về cơ bản là các mô hình biểu diễn các thực thể dữ liệu hoặc API khác nhau. Các tài nguyên này giúp cấu trúc quản lý dữ liệu của ứng dụng của bạn.
  • Vô hiệu hóa: Tự động vô hiệu hóa dữ liệu sau khi đột biến thành công (ví dụ: tạo, cập nhật hoặc xóa tài nguyên), đảm bảo rằng UI được cập nhật bằng dữ liệu mới nhất.
  • Caching: Cache dữ liệu để cải thiện hiệu suất và loại bỏ các lệnh gọi API trùng lặp.
  • Cập nhật : Nghĩa là nó sẽ cập nhật UI trước khi lệnh gọi API thực tế hoàn tất. Điều này nâng cao trải nghiệm của người dùng bằng cách giảm độ trễ được nhận biết

3. Xử lý lỗi:

Refine nhận các lỗi được mở rộng từ HttpError. Nếu bạn có notificationProvider, Refine sẽ tự động hiển thị thông báo khi xảy ra lỗi.
Xác thực phía máy chủ: Hiển thị lỗi đến từ API trên các trường biểu mẫu tương ứng.
Cập nhật: Cập nhật ngay lập tức UI khi bạn gửi đột biến và tự động hoàn nguyên các thay đổi nếu xảy ra lỗi trong quá trình đột biến.

const { data, error, isError, isLoading } = useOne(
  {resource: "products",id: "non-existing-id", queryOptions: {retry: 0,},
});
if (isError) {
    return (
        <div>
            <h1>Error</h1>
            <p>{error.message}</p>
        </div>
    );
}

4. Xử lý dữ liệu trả về:

Refine cung cấp các lựa chọn tiện ích cho việc phân trang, lọc và sắp xếp dữ liệu được trả về

Chúng ta sẽ sử dụng: sorts, filters và pagination thêm vào trong các hook CRUD để có thể làm điều này

export const HomePage = () => {
    const { data: products } = useList({
        resource: "products",
        pagination: { current: 1, pageSize: 5 },
        sorters: [{ field: "id", order: "DESC" }],
        filters: [{ field: "material", operator: "eq", value: "Wooden" }],
    });

    return (
        <div>
            <h2>Wooden Products</h2>
            <ul>
                {products?.data?.map((product) => (
                    <li key={product.id}>
                       <p>
                            {product.id}
                            <br />
                            {product.name}
                            <br />
                            Price: {product.price}
                            <br />
                            Material: {product.material}
                       </p>
                    </li>
                ))}
            </ul>
        </div>
    );
};

Kết luận:

Bài viết là một số tổng hợp ngắn gọn về cách Refine có thể hoạt động trong việc fetching data, cung cấp cho người đọc các hooks cơ bản và hữu ích khi tích hợp thư viện vào dự án của mình. Qua đây, hi vọng rằng mọi người sau khi đọc bài viết có thể có thêm kiến thức về refine cũng như có thể giúp ích cho các dự án trong tương lai nếu dùng thư viện này.

Avatar photo

Clean Code: Nguyên tắc viết hàm trong lập trình…

Trong quá trình phát triển phần mềm, việc viết mã nguồn dễ đọc, dễ hiểu là yếu tố then chốt để đảm bảo code...
Avatar photo Dat Tran Thanh
3 min read

Leave a Reply

Your email address will not be published. Required fields are marked *