Banner 1
Banner 2
hero

Phạm Văn Tú

4518 thành viên

  1. Trang chủ /
  2. Reactjs & Nextjs /
  3. Tìm hiểu cơ chế caching của React Query như thế nào nghen

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 0s

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

hero