Search code examples
javascriptreactjsreact-querytanstackreact-query

TypeError: Cannot read from private field in Tanstack React Query


Currently, I am using Tanstack Query V5 in my vite-react project.

Whenever I try to use invalidateQueries it throws an error TypeError: Cannot read from private field

I want is, when the mutation for invoice deletion will trigger it refetch the invoice list again

main.tsx

import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter as Router } from 'react-router-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
const queryClient = new QueryClient()
import App from './App.tsx'
import { DashboardProvider } from './context/Dashboard.context'
import { Toaster } from '@/components/ui/toaster'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Router>
      <QueryClientProvider client={queryClient}>
        <DashboardProvider>
          <App />
          <Toaster />
        </DashboardProvider>
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </Router>
  </React.StrictMode>
)

Here is my code for useQuery

const { isFetching, data } = useQuery({
  queryKey: ['invoiceList', page, limit],
  queryFn: async () => {
    const { data } = await apiRequest.get('/client/invoiceList', {
      params: { page, limit },
    })
    return data
  },
})

Here is my code for useMutation & invalidateQueries

const { invalidateQueries } = useQueryClient()
const { mutate, isPending } = useMutation({
  mutationFn: async () => {
    return await apiRequest.delete('/client/deleteInvoice', {
      params: { id: invoice?.id },
    })
  },
  onSuccess: () => {
    toast({
      variant: 'success',
      title: 'Invoice deleted successfully',
      description: `Invoice ${invoice?.reference} has been deleted successfully`,
    })
    invalidateQueries({ queryKey: ['invoiceList'] })
  },
  onError: (error) => {
    console.log(error?.message)
    handleError(error, toast)
  },
})

Here is the complete error -

TypeError: Cannot read from private field
    at __accessCheck (chunk-TIUEEL27.js?v=ae984db9:41:11)
    at __privateGet (chunk-TIUEEL27.js?v=ae984db9:44:3)
    at chunk-PF574KJM.js?v=ae984db9:1620:7
    at Object.batch (chunk-PF574KJM.js?v=ae984db9:499:16)
    at invalidateQueries (chunk-PF574KJM.js?v=ae984db9:1619:26)
    at onClick (index.tsx:81:15)
    at HTMLUnknownElement.callCallback2 (chunk-EL3PUDHE.js?v=ae984db9:3674:22)
    at Object.invokeGuardedCallbackDev (chunk-EL3PUDHE.js?v=ae984db9:3699:24)
    at invokeGuardedCallback (chunk-EL3PUDHE.js?v=ae984db9:3733:39)
    at invokeGuardedCallbackAndCatchFirstError (chunk-EL3PUDHE.js?v=ae984db9:3736:33)

Initially, I thought this error was occurring for the version. So I update the version from 5.14.2 to ^5.26.3. But the problem remains unsolved.


Solution

  • The queryClient you get from useQueryClient is an instance of the class QueryClient that uses private fields, simplified example:

    class QueryClient {
      #foo = 'bar'
    
      invalidateQueries() {
        return this.#foo
      }
    }
    
    const queryClient = new QueryClient()
    

    If you destructure queryClient like so

    const { invalidateQueries } = queryClient
    

    you are losing the context of the function, so when you call it, you're calling it without access to this.#foo:

    invalidateQueries() // throws an error
    
    // but this keeps working
    queryClient.invalidateQueries() // 'bar'
    

    This is expected behaviour of JS with regards to context (the value of this).

    --

    The solution for you is to not destructure:

    const queryClient = useQueryClient()
    
    queryClient.invalidateQueries()