Bài viết này mình sẽ giới thiệu với mọi người một package hữu ích khi làm viêc với reactjs
Khi mình mới bắt đầu học về Reactjs thì hầu hết các tài liệu về làm việc với Api được ví dụ bằng cách sử dụng useEffect. Đơn giản vì useEffect đáp ứng khá tốt cho 1 project nhỏ, không cần khả năng lưu trữ cache, và hơn hết là quên thuộc với người mới sử dụng reactjs.
Tuy nhiên khi va vào những dự án thật thì chúng ta cần 1 cách để gọi Api nhiều hơn là chỉ chạy, ví dụ như khả năng lưu cache hay retry, gọi lại api khi người dùng focus vào màn hình… Đó là những gì mà mình muốn trình bày trong bài viết này: package hooks function useQuery và useQueries.
useQuery
Đầu tiên là những lợi ích mà useQuery sẽ giúp bạn:
- Window focus refetching: khi người dùng rời khỏi tab ứng dụng của bạn, React Query sẽ đánh dấu dữ liệu là “cũ” và tìm hiểu lại dữ liệu đó khi người đó quay lại.
- Request retry: bạn có thể đặt số lần thử lại cho bất kỳ yêu cầu nào để chống lại các lỗi ngẫu nhiên.
- Prefetching: nếu ứng dụng của bạn cần dữ liệu mới sau khi có yêu cầu cập nhật, bạn có thể tìm nạp trước truy vấn bằng một khóa cụ thể và React Query sẽ cập nhật nó trong nền.
- Optimize Updates: khi bạn chỉnh sửa hoặc xóa một mục trong danh sách, bạn có thể đưa ra bản cập nhật lạc quan cho danh sách.
- Cấu hình useQuery
Sử dụng useQuery rất dễ dàng cho người mới:
Đầu tiên tại file App.js. hãy khai báo QueryClientProvider và bọc nó cho các children compoment.
import { QueryClient, QueryClientProvider } from 'react-query'
const queryClient = new QueryClient()
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
Tiếp tục, giả sử chúng ta có một hàm fetching
sử dụng Axios
để lấy dữ liệu các bài viết
async function fetchingPosts() {
const res = await axios.get("href api");
return res.data;
}
Việc kết hợp hàm tìm nạp dữ liệu của chúng ta với React-Query
sẽ vơ cùng đơn giản
import React from 'react'
import { useQuery } from 'react-query'
import fetchingPosts from 'src/core/services/fetchingPosts.js'
export const Articles = () => {
const { data, error, isError, isLoading } = useQuery(['articles'], fetchingPosts)
if (isLoading) {
return <span>Đang tải...</span>
}
if (isError) {
return <span>Have an errors: {error.message}</span>
}
return (
<ul>
{data.map(article => (
<li key={article.id}>{article.title}</li>
))}
</ul>
)
}
Bằng cách gọi hook
React-query và lấy ra những biến ràng buộc dữ liệu mà React-Query đã quy định trước đó, nó hoàn toàn dễ dàng sử dụng và dễ tiếp cận đối với chúng ta.
2. Tìm nạp dữ liệu hiện đã tốt hơn
Tại sao nó lại tốt hơn so với cách tìm nạp dữ liệu thông thường với useEffect
. Khi chúng ta truy vấn với cùng một key
đã định nghĩ ở useQuery, React-Query ngay lập tức trả về dữ liệu đã được fetch trước đó và tìm nạp dữ liệu mới.
Khi tập dữ liệu thứ hai giống với tập đầu tiên, Truy vấn React sẽ giữ cả hai làm tham chiếu mà không buộc tải lại. Đó là một cải tiến to lớn đối với trải nghiệm người dùng.
3. Xử lí dữ liệu tại caching
Hàm được đóng gói kèm theo nhiều phương thức giúp bạn xử lý bộ nhớ đệm cache.
invalidateQueries
phương thức đánh dấu một truy vấn có khóa đã cho là không hợp lệ để làm cho Truy vấn React tìm nạp lại dữ liệu đó. Bạn có thể sử dụng phương pháp đó trong hook useMutation sau khi cập nhật thành công (ví dụ bên dưới).setQueryData
được sử dụng cho việc cải thiện cập nhật dữ liệu đã lưu vào bộ nhớ đệmprefetchQuery
phương thức giúp bạn tìm nạp lại một số dữ liệu trước khi cần và rendered với useQuery. Nếu bạn biết khi nào người dùng cần dữ liệu đó, sử dụng phương thức này là một cách tìm nạp dữ liệu cải thiện nhiều về trải nghiệm người dùng.clear
đơn giản là xoá tất cả các cache đã lưu
Để sử dụng những phương thức này, bạn sẽ cần import
useQueryClient
hook từ React-Query. Sau đó, assign nó vào một biến dưới dạng const queryClient = useQueryClient
và gọi các phương thức bên trong nó bằng cách gọi một object thông thường.
useQueries
useQuery chỉ trả về 1 giá trị định dạng hỗ trợ cho 1 function call Api. Vậy nếu muốn gọi nhiều hơn 1 Api trong compoment thì sao? Đó là lý do useQueries được sinh ra với các đối tượng truy vấn tương tự useQuery nhưng lại support gọi nhiều hơn 1 Api.
Giá trị của useQueries trả ra ở dạng mảng và không khác useQuery về config định dạng. Vì thế sử dụng useQueries cũng rất đơn giản, dưới đây là 1 ví dụ.
const results = useQueries({
queries: [
{ queryKey: ["post", 1], queryFn: fetchPost, staleTime: Infinity },
{ queryKey: ["post", 2], queryFn: fetchPost, staleTime: Infinity },
],
});
Tuy nhiên vì trả về nhiều Api trong 1 hook function nên useQueries không hỗ trợ context đơn giản như useQuery. Để sử dụng context, ta có thể làm bằng cách định nghĩa context:
context?: React.Context<QueryClient | undefined>
Kết Luận
Trên đây là bài viết mình muốn giới thiệu sơ qua với mọi người về useQuery và useQueries. Với cá nhân thì mình thấy đây là 1 hooks hỗ trợ rất tốt cho việc call API, cải thiện đoạn code ngắn hơn và có thể lưu trữ cache giảm tải quá trình loading.
Tuy nhiên quản lý cache cho 1 project gọi api bằng useQuery cũng là 1 vấn đề cần chú ý. Khá nhiều lỗi có thể phát sinh nếu ta sử dụng bừa bãi hook này khi project lớn hơn. Mình sẽ có 1 bài viết để xử lý kỹ lưỡng vấn đề này giúp mọi người khắc phục nó. Xin cảm ơn.