I am trying to understand the Composition-API Reactivity in vue3. I want to build a search bar, which shall instantly show me the results in the template.
For that, I have a reactive variable search and a reactive variable results.
If I declare results as ref() which should automatically convert to reactive() due because it's an Array [EXAMPLE A] or declare directly this array as reactive() [EXAMPLE B] the results are not rendered directly in the template. I write one letter, nothing happens, but when I write the second letter, I see the result of the search before with the single letter.
When I deeply nest the results [EXAMPLE C], then it works, I see instantly all results.
Why is that? I don't understand why A or B does not work.
<script setup>
let search = ref("");
// EXAMPLE A
// This does not work, the search results are shown one "tick" later
const results = ref([]);
// EXAMPLE B
// This does not work, the search results are shown one "tick" later
const results = reactive([]);
// EXAMPLE C
// This does work, when the result array is deeply-nested in a reactive object
const query = reactive({ results: [] });
watch(search, (value) => {
axios
.post("/search", { search: value })
.then(response => {
// EXAMPLE A / B
results = response.data;
// EXAMPLE C
query.results = response.data;
})
.catch();
});
</script>
<template>
<!-- EXAMPLE A / B -->
<div v-for="product in results" :key="product.id">
<div>{{ product.id }}</div>
<div>{{ product.name }}</div>
</div>
<!-- EXAMPLE C -->
<div v-for="product in query.results" :key="product.id">
<div>{{ product.id }}</div>
<div>{{ product.name }}</div>
</div>
</template>
CodePudding user response:
I am assuming that the sample code that you posted is a contrived example, since it gives runtime errors. In JS, you can't reassign to const
, which you are doing several times within your sample code. Therefore, I can't reproduce the behavior that you claim to see.
To fix Example A and Example B, you need to change how you assign the response to the reactive object.
- Example A - you are using a
ref
, where you need to assign to thevalue
property of the ref -results.value = response.data
. See the Vue docs on ref for more. - Example B - you can't reassign to a
reactive
- this is a limitation of usingreactive
. You can work around this either by usingObject.assign
(see https://stackoverflow.com/a/65733741/6767625) or by using Example C, which as you noted works fine.