Here is my Vue3 app code:
<template>
{{ names_data }}
</template>
<script>
import getData from "./composables/getData"
export default {
name: "App",
setup() {
var filenames = ["test1.json", "test2.json"];
const { names_data, error, load_data } = getData(
filenames
);
load_data();
console.log("names", names_data)
console.log("error", error)
return { names_data };
},
};
</script>
The imported composable function is the following:
import { ref } from "@vue/runtime-core";
const getData = (filenames) => {
const names_data = ref([])
const error = ref(null)
const load_data = async () => {
try {
var promises = [];
for (let i = 0; i < filenames.length; i ) {
var filename = filenames[i]
promises.push(
fetch(`data/${filename}`).then(
(res) => (res.ok && res.json()) || Promise.reject(res)
)
);
}
const data = await Promise.all(promises);
names_data.value = data
} catch (err) {
error.value = err.message;
console.log(error.value);
}
};
return { names_data, error, load_data }
};
export default getData
and the data files contain the following:
test1.json
{
"members": {
"0": "Alice",
"1": "Bob",
"2": "Charlie"
}
}
test2.json
{
"members": {
"0": "David",
"1": "Elizabeth",
"2": "Fred"
}
}
This all works: I can see the names_data
from the template showing on screen. However in the console the names_data
appears as follows:
RefImpl {_shallow: false, dep: undefined, __v_isRef: true, _rawValue: Array(0), _value: Proxy} dep: Set(1) {ReactiveEffect} __v_isRef: true _rawValue: (2) [{…}, {…}] _shallow: false _value: Proxy {0: {…}, 1: {…}} value: (...) [[Prototype]]: Object
I want to be able to access the values in names_data
for further processing, like putting them in a table, but when I do console.log(names_data.value)
in the App I get a Proxy object to an empty array.
I think the names_data
object loses reactivity somehow, as it is not updated when load_data()
is called. But it clearly is reactive in the template. So I'm confused about what is going on here.
How can I access the value of the ref to process it further?
CodePudding user response:
It works as expected. Without using reactivity this would result in this popular race condition. The point of using reactivity is that values are reactive and can be composed in other places through composition API.
In this case it's unnecessary to wait for load_data
to complete in setup
body. It's supposed to be accessed at the time when a value is available:
const { names_data, error, load_data } = getData(...);
load_data();
watch(names_data, data => {
console.log(data);
});