N
Nuxt9mo ago
Kuroro

Differents watch sources using useState

<script setup lang="ts">
const { find } = useStrapi()

const { offset, search, selectedFilter } = useTableParams()

const { data: campaigns } = await useAsyncData(
'campaigns',
() => find<Campaign>('campaigns', {
pagination: offset.value
}),
{
transform: (data: Strapi4ResponseMany<Campaign>) => {
pagination.value = data.meta.pagination as MetaResponsePaginationByPage
return data.data
},
// ! Here I'm giving offset.value for useState global reactive var that "hosts" an object
// ! But for simple global variables like string, I have to give the reactive part (ok)
// ? why ?
watch: [offset.value, search, selectedFilter]
})
</script>
<script setup lang="ts">
const { find } = useStrapi()

const { offset, search, selectedFilter } = useTableParams()

const { data: campaigns } = await useAsyncData(
'campaigns',
() => find<Campaign>('campaigns', {
pagination: offset.value
}),
{
transform: (data: Strapi4ResponseMany<Campaign>) => {
pagination.value = data.meta.pagination as MetaResponsePaginationByPage
return data.data
},
// ! Here I'm giving offset.value for useState global reactive var that "hosts" an object
// ! But for simple global variables like string, I have to give the reactive part (ok)
// ? why ?
watch: [offset.value, search, selectedFilter]
})
</script>
export const useTableParams = () => {
const offset = useState('offset', () => ({
page: 1,
pageSize: 5,
withCount: true
}))

const search = useState('search', () => '')
const selectedFilter = useState('selectedFilter', () => 'all')

return { offset, selectedFilter, search }
}
export const useTableParams = () => {
const offset = useState('offset', () => ({
page: 1,
pageSize: 5,
withCount: true
}))

const search = useState('search', () => '')
const selectedFilter = useState('selectedFilter', () => 'all')

return { offset, selectedFilter, search }
}
Any ideas for my case ? I'm just asking why I need to watch for offset.value in my useAsyncData() (which is a global reactive object created with useState) and why I don't need it to for other variables (like number or string...) What are the differences between simple primitive types that I don't see ? I'm pretty sure it's for you, @manniL / TheAlexLichter 👋🏼😁 Thanks y'all ❤️
15 Replies
Cheaterman
Cheaterman9mo ago
Don't ping people randomly, it's rude Other than that what happens if you return a ref
Kuroro
KuroroOP9mo ago
Hm? Alex is saying « feel free to ping on discord » on his YouTube channel… I ping him because he treats reactivity problems on his last video, it’s not random
Cheaterman
Cheaterman9mo ago
OK - answer my question though
Kuroro
KuroroOP9mo ago
Where would you return a ref?
Cheaterman
Cheaterman9mo ago
In the useState initializer, as per the docs
useState('mything', () => ref({something: 'something_else'}));
useState('mything', () => ref({something: 'something_else'}));
Basically just add ref before your current brackets In fact I just realized this probably won't change much since you're currently using .value ; rather than ref() you may want to try reactive() to get rid of .value Did it work?
Kuroro
KuroroOP9mo ago
I can’t test currently, will tell you asap
manniL
manniL9mo ago
I feel setting the pagination value in transform is "wrong" 🤔 But a running repro would be better
Kuroro
KuroroOP9mo ago
It's not. I'm maybe wrong, but i think useState is already returning a Ref, so i don't get it when you talk about specifying a ref/reactive in useState (make it nosense for me, but, once again, i'm maybe wrong) And, if you find the docs page where it's specified, i would be happy to see it.
Kuroro
KuroroOP9mo ago
Oh ok, I probably shouldn't do assignation here... Strapi API returns an object with two keys, trying to deal with it without wrapping my useAsyncData in a function... maybe should I ? there's a minimal repro with a dummy API, but it reproduces my behavior : https://stackblitz.com/edit/nuxt-starter-cicj7t?file=components%2FTodosTable.vue See comments in TodosTable.vue 🙂
jmbdx
StackBlitz
Nuxt - useState & useAsyncData - StackBlitz
Can't trigger the useAsyncData function each time I change my composable Composable is well updated, but the query is never re-triggered
Cheaterman
Cheaterman9mo ago
Doesn't mean that you shouldn't try it 🙂 this works for me:
export const useTableParams = () => {
const limit = useState('params.limit', () => 2);

const search = useState('search', () => '');

return { params: reactive({ limit }), search };
};
export const useTableParams = () => {
const limit = useState('params.limit', () => 2);

const search = useState('search', () => '');

return { params: reactive({ limit }), search };
};
Not quite what I anticipated but at least it gets the job done The relevant doc page: https://nuxt.com/docs/api/composables/use-state It reads:
init: A function that provides initial value for the state when not initiated. This function can also return a Ref.
IDK if it means it has to return a ref to be reactive but... here we are Either way I know it's complicated and hard to make sense of, don't worry you'll eventually get there 🙂 Just give it some time I suppose haha
Kuroro
KuroroOP9mo ago
Ahah thanks! That's the first time I see this kind of trick. It wouldn't be the best case in my opinion, because we're obliged to define each property of the object into different variables, It feels a bit hacky no? Anyway, thanks for your time As I said in my repro, I got it working too, but, i'm really looking for a technical explanation & why not, have an advice on the best way to go ! 🙂
Cheaterman
Cheaterman9mo ago
So, I think it's not "bad" to have one property per variable, because that's kind of why Vue has fine-grained reactivity etc 😄 As to why you want to use .value, I believe it's because otherwise you're not observing the proxy object for changes, you're observing a ref to it which itself isn't changing unless you re-assign a whole object ie less params.limit = xyz and more params = {...params, limit: xyz} But that's just a guess (might not be exactly correct but it's a mental model that "works" for me)
Kuroro
KuroroOP9mo ago
mhh ok I get it, but isn't it a bit strange if we have to manage a larger object? To be precise, in my original codebase, i'm dealing with two kind of types, an object type and a primitive type (string/number/whatever). As you can see, types returned by useState are the same (Ref<T> if I can put it that way) So, thats why I was wondering why I should use .value for the object part, and shouldn't for primitive part
No description
No description
Kuroro
KuroroOP9mo ago
As you can see in screenshots, IDE is not really explicit... maybe should I log them to see further
Cheaterman
Cheaterman9mo ago
I don't think IDE is going to help 😦 And I expected reactive() to help change that ref into something that can be observed without .value, but it didn't work That's why I gave you the solution where each individual property of the object is a ref 🙂 Might not be ideal but it does "make sense" IMHO Either that or you can go back to your original solution with .value - it does save some typing
Want results from more Discord servers?
Add your server