I am wondering how to destructure an object prop without having to type data.title
, data.keywords
, data.image
etc. I've tried spreading the object directly, but inside the template it is undefined if I do that.
Would like to return directly {{ title }}
, {{ textarea }}
etc.
My code:
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script lang="ts">
import { useSanityFetcher } from "vue-sanity";
import { defineComponent, reactive, toRefs } from "vue";
export default defineComponent({
name: "App",
setup: () => {
const articleQuery = `*[_type == "article"][0] {
title,
textarea,
}`;
const options = {
listen: true,
clientOnly: true,
};
const res = useSanityFetcher<any | object>(articleQuery, options);
const data = reactive(res.data);
return toRefs(data);
},
});
</script>
CodePudding user response:
The Vue docs actually recommend not destructing props because of the way reactivity works but if you really want to something like this should work:
const res = useSanityFetcher<any | object(articleQuery, options);
const data = reactive(res.data);
return toRefs(data);
Don't forget to import reactive and toRefs.
CodePudding user response:
Considering that useSanityFetcher
is asynchronous, and res
is reactive, it's incorrect to access res.data
directly in setup because this disables the reactivity. Everything should happen in computed
, watch
, etc callback functions.
title
, etc properties need to be explicitly listed in order to map reactive object to separate refs with respective names - can probably be combined with articleQuery
definition or instantly available as res.data
keys
E.g.:
const dataRefs = Object.fromEntries(['title', ...].map(key => [key, ref(null)]))
const res = ...
watchEffect(() => {
if (!res.data) return;
for (const key in dataRefs)
dataRefs[key] = res.data[key];
});
return { ...dataRefs };
CodePudding user response:
Destructuring the object is not the problem, see Vue SFC Playground
<script lang="ts">
//import { useSanityFetcher } from "vue-sanity";
import { defineComponent, reactive, toRefs } from "vue";
export default defineComponent({
name: "App",
setup: () => {
const res = {
data: {
title: 'Hi there'
}
}
const data = reactive(res.data);
return toRefs(data);
},
});
</script>
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
It may simply be the space between the filter and the projection in the GROQ expression
const articleQuery = `*[_type == "article"][0]{ title, textarea }`;
See A description of the GROQ syntax
A typical GROQ query has this form:
*[ <filter> ]{ <projection> }