1
import { useQuery } from "vue-query";
const { isLoading, data /* read only */, error, isError, refetch } = useQuery("todo", todo)

I just found out data returned by vue-query is read only. Vue-query is similary project to React-query. You can find it here.
If I do data.todoList.push(newTodo) then I got the following warning

[Vue warn] Set operation on key "xxx" failed: target is readonly

My question is 1) How do I change the value returned by vue-query? 2) If I need to change the returned data, what is the best way to do it?

2
  • I don't know Vue at all, but why do you need to mutate it? Can't you just do [...data.todoList, newTodo]? Commented Jan 19, 2023 at 20:36
  • [...data.todoList, newTodo] does not work, same warning, no effect. I am not familiar with correct pattern for vue-query. Why they make the returned data read only? Commented Jan 19, 2023 at 20:42

4 Answers 4

1

it is intentional to NOT be able to change the returned content, see github issue.

just save/copy the returned data into a reactive variable and modify it as u wish.

Sign up to request clarification or add additional context in comments.

Comments

1

The accepted answer did not work for me, even if I used the [...] operator. What did work was using the toRaw function from Vue, to remove the proxy wrapper around each object before assigning the data to my reactive variable.

watch(
  () => productsQuery.data.value,
  (newData) => {
    products.value = toRaw(newData ?? []);
  }
);

Comments

1

You can use the method toRaw , worked for me

Query call

usage in template

Comments

1

TL;DR - Do not use toRaw(). Use something like structuredClone(toRaw(...)).

I tested using toRaw() and it seems to work on the surface, but I don't think it's going to work as intended. What's actually happening is that it gives you a reference to the underlying object that bypasses vue-query's read-only proxy.

So if you use toRaw() and store that in a mutable ref, mutating that ref is going to end up mutating the data in the vue-query cache as well.

This is why the Vue docs do not recommend using toRaw() to get a persistent reference to an object (https://vuejs.org/api/reactivity-advanced.html#toraw):

toRaw() can return the original object from proxies created by reactive(), readonly(), shallowReactive() or shallowReadonly().
This is an escape hatch that can be used to temporarily read without incurring proxy access / tracking overhead or write without triggering changes. It is not recommended to hold a persistent reference to the original object. Use with caution.

A better solution here is to do something like structuredClone(toRaw(...)). This will give you an actual copy of the vue-query data that can be mutated without affecting the vue-query cache.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.