Tìm hiểu cơ chế caching của React Query như thế nào nghen
Lại là TúPêVê đây 😜. Bài này mình cùng tìm hiểu một số khái niệm quan trọng cũng như cơ thế caching của React Query như thế nào nhé 💋
Một số khái niệm ae cần lưu ý nhé
staleTime (default 0 ms): Thời gian data được cho là đã cũ. Khi get data xong thì sau một thời gian mình quy định thì data nó sẽ tự cũ. Mặc định 0 là khi get xong là nó cũ ròi á
Ae có cài react dev tool thì chỗ stale
là nó hiển thị data đã cũ (stale) và thêm cái là active nữa thôi (để cho mình biết đang gọi query key nào á kiểu vậy subcribe
) mấy cái dưới cũng là cũ nhưng inactive á nghen
cacheTime (default 5601000 ms = 5 phút) : Thời gian data sẽ bị xóa ra khỏi bộ nhớ đệm. Data có thể cũ (stale) nhưng nó chưa bị xóa ra khỏi bộ nhớ đệm vì mình set staleTime < cacheTime. Thường thì người ta sẽ set staleTime < cacheTime . Ví dụ lúc phân trang mình ở trang 1 mình call api có page = 1, trang 2 mình call api có page = 2 thì khi sang trang 1 và 2 lại thì nó thấy data 2 page này còn lưu ở bộ nhớ đệm nên sẽ gọi data lưu ở cached ra và fetch ngầm ở dưới nếu có data mới khác data cache thì nó tự update lại data cached cho mình luôn 😍 inactive: Là khi data đó không còn component nào subcribe cả
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
// result là 1 object chứa 1 vài state rất quan trọng như status, fetchStatus...
Những state về khoảnh khắc của data
isLoading hoặc status === ‘loading’: Query chưa có data isError hoặc status === ‘error’: Query xảy ra lỗi isSuccess hoặc status === ‘success’: Query thành công và data đã có sẵn
Những state về data
error: Nếu isError === true hoặc hoặc status === ‘error’ thì error sẽ xuất hiện data: Nếu isSuccess === true hoặc status === ‘success’ thì data sẽ xuất hiện
Đặc biệt là fetchStatus
isFetching hoặc fetchStatus === ‘fetching’: Đang fetching API isPaused hoặc fetchStatus === ‘paused’: Query muốn fetch API nhưng bị tạm dừng vì 1 số lý do nào đó fetchStatus === ‘idle’: Query không làm gì cả, chạy xong rồi đang rảnh =))
Nói chung đọc tới đây ae cũng rối cmnr kaka. Tóm lại như này cho khỏe
status cho thông tin data có hay không fetchStatus cho thông tin về queryFn có đang chạy hay không
Ví dụ thực tế ri cho ae dễ hình dung nghen, không hình dung được thì ib hỏi mình 😁 kaka
Click trang 1 call api thì loading = true do chưa có call xong rồi thì loading = false, trang 2,3..n cũng vậy
Khi quay về trang 1 hoặc những trang trước đó lại thì loading sẽ là false luôn vì nó đã có data trước đó rồi, nhưng nó vẫn call api ngầm ở dưới á nếu có thay đổi thì nó sẽ cập nhật lại data mới thoi
=> (isFetching = true lúc call api, khi call xong thì tất nhiên isFetching về false rồi)
Cơ chế caching data
Một data mà đã stale (cũ) thì khi mà gọi lại query của data đó, nó sẽ fetch lại api. Nếu không stale thì không fetch lại api. Vì mặc định là staleTime là 0 ms call xong nó cũ rồi. Hoặc setiing staleTime lên 60 * 1000 để 1 phút sau nó mới cũ thì click lại trong 1 phút thì nó không call api Một data mà đã bị xóa khỏi bộ nhớ (tức là quá thời gian cacheTime) thì khi gọi lại query của data đó, nó sẽ fetch lại api (Dĩ nhiên roài). Nếu còn chưa bị xóa khỏi bộ nhớ nhưng đã stale thì nó sẽ trả về data cached và detch api ngầm, sau khi fetch xong nó sẽ update lại data cached và trả về data mới cho bạn
Ví dụ siêu dễ hiểu cho ae về vòng đời caching của React Query
Mặc định mình dùng cacheTime là 5 phút và staleTime là 0 nha
function A() {
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
}
function B() {
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
}
function C() {
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
}
A
component được mount
Vì không có query nào với ['todos']
trước đó, nó sẽ fetch data
Khi fetch xong, data sẽ được cache dưới key là ['todos']
hook đánh dấu data là stale
(cũ) vì sau 0
s
Bây giờ thì B
component được mount ở một nơi nào đó
Vì cache data ['todos']
đã có trước đó, data từ cache sẽ trả về ngay lập tức cho component B
Vì cache data ['todos']
được cho là đã stale
nên nó sẽ fetch api tại component B
Không quan trọng function fetchTodos
ở A
và B
có giống nhau hay không, việc fetch api tại B
sẽ cập nhật tất cả các state query liên quan của B
và A
vì 2 component cùng key => cùng subcribe đến một data
Khi fetch thành công, cache data ['todos']
sẽ được cập nhật, cả 2 comonent A
và B
cũng được cập nhật data mới
Bây giờ thì A
và B
unmount, không còn sử dụng nữa, không còn subcribe đến cache data ['todos']
nữa nên data ['todos']
bị cho là inactive
Vì inactive
nên cacheTime
sẽ bắt đầu đếm ngược 5 phút
Trước khi cacheTime
hết thì ông C
comopnent được mount. cache data ['todos']
được trả về ngay lập tức cho C
và fetchTodos
sẽ chạy ngầm. Khi nó hoàn thành thì sẽ cập nhật lại cache với data mới.
Cuối cùng thì C
unmount
Không còn ai subcribe đến cache data ['todos']
trong 5 phút tiếp theo nữa và cache data ['todos']
bị xóa hoàn toàn