Update multiple keys in cache after mutation with React Query

Viewed 725

I'm using React Query and I want to update cache after the mutation, but I want to update multiple keys in one go.

I have "invoices" and ["invoice", 1] and I update it as follows:

queryClient.setQueryData("invoices", ({invoices}) => {
    return {
        invoices: [
            ...filter(invoices, invoice => invoice.id !== activeInvoice),
            {
                ...find(invoices, invoice => invoice.id === activeInvoice),
                customer: data?.updateInvoiceCustomer?.customer
            }
        ]
    }
})

queryClient.setQueryData(["invoice", activeInvoice], ({invoice}) => {
    return {
        invoice: {
            ...invoice,
            customer: data?.updateInvoiceCustomer?.customer
        }
    }
})

Thus, now I do it per key. Is there any way to do it in one go and to use something like this:

queryClient.setQueriesData(["invoices", ["invoice", activeInvoice]], ({invoices, invoice}) => {
    return {
        invoices: [
            ...filter(invoices, invoice => invoice.id !== activeInvoice),
            {
                ...find(invoices, invoice => invoice.id === activeInvoice),
                customer: data?.updateInvoiceCustomer?.customer
            }
        ],
        invoice: {
            invoice: {
                ...invoice,
                customer: data?.updateInvoiceCustomer?.customer
            }

        }
    }
})

Thanks

1 Answers

The API is a bit different, to select both queries.

First option, you would have to change the keys to be ['invoices'] and ['invoices', id], then you can "match them partially", just by providing ['invoices'] to setQueriesData.

But even then you would have to check which one is which inside the updater:

queryClient.setQueriesData(["invoices"], (data) => {
  if (Array.isArray(data)) {
    // updating the list
  } else {
    // updating the resource
    if (data.id === id) {
      // the filter matches not only ['invoices', id] but all ids
    }
  }
})

To be honest, it doesn't look very ergonomic.

Second option, you can make it a bit more readable by using a predicate as well instead

queryClient.setQueriesData({
  predicate: function ({ queryKey }) {
    if (queryKey[0] === 'invoices') {
      return true
    }
    if (queryKey[0] === 'invoice' && queryKey[1] === id) {
      return true
    }
    return false
  }
}, (data) => {
  if (Array.isArray(data)) {
    // updating the list
  } else {
    // updating the resource
  }
})

But to be honest, your original code still looks more readble to me

Related