https://github.com/supabase-community/vue-supabase
I've seen a few of these ^ Vue wrappers for Supabase, but I have not seen an explanation as to why one would want to use them.
Can someone point me to what the differences are or even better, why using vue-supabase is better?
Why is doing...
<script setup lang="ts">
import { useSupabase } from "vue-supabase";
const supabase = useSupabase();
const { data, error } = await supabase.from("events").select("*");
</script>
better than doing...
<script setup lang="ts">
import { supabase } from "../supabase";
const { data, error } = await supabase.from("events").select("*");
</script>
?
I apologize ahead of time if the answer here is simple and I just missed it.
Related
I can't display object in Vue 3 script setup. I used ref, reactive and standard variables but all scenarios is unsuccessful.
I want to reflect the response from the getDetail request to the screen. getDetail is fetching this data asynchronously. I run into a problem in every scenario.
ref() usage
<script setup>
let movie = ref([])
const getMovieData = async ()=> {
try {
const data = await getDetail('movie', route.params.id)
movie.value.push(data)
}
catch (e){
console.log(e)
}
}
getMovieData()
</script>
<template>
<h1>{{movie[0].original_title}}</h1>
</template>
I am able to show data in this usage but I am getting these errors
reactive() usage
<script setup>
let movie = reactive({
data:null
})
const getMovieData = async ()=>{
try {
const data = await getDetail('movie', route.params.id)
movie.data = data
}catch (e){
console.log(e)
}
}
getMovieData()
</script>
<template>
<h1>{{movie.data.original_title}}</h1>
</template>
In this usage I can show data but I get similar errors
Standart variable usage
<script setup>
let movie
const getMovieData = async ()=>{
try {
const data = await getDetail('movie', route.params.id)
movie =data
}catch (e){
console.log(e)
}
}
getMovieData()
</script>
<template>
<h1>{{movie.id}}</h1>
</template>
In this usage, the data does not appear on the screen, because the movie object is formed asynchronously.
How do I manage to display this object on the screen in the most correct way without getting an error?
Write a v-if <h1 v-if="movie && movie.length">{{movie[0].id}</h1> So it only renders when data is available.
Template code runs immediately on component creation. In each case, before movie has been asynchronously assigned, your template code is trying to access some non-existent property. optional chaining is arguably the easiest way to prevent these types of errors:
movie[0]?.original_title
Another option is to provide a default value that matches your template usage so it doesn't error out:
let movie = ref([
{
original_title: ''
}
])
I have a vue composable that needs to fire an event. I naively set it up as follows:
*// composable.js*
import { defineEmits } from "vue";
export default function useComposable() {
// Vars
let buffer = [];
let lastKeyTime = Date.now();
const emit = defineEmits(["updateState"]);
document.addEventListener("keydown", (e) => {
// code
emit("updateState", data);
}
// *App.vue*
<template>
<uses-composables
v-show="wirtleState.newGame"
#updateState="initVars"
></uses-composables>
</template>
<script setup>
const initVars = (data) => {
//code here
}
// usesComposable.vue
<template>
<button #click="resetBoard" class="reset-button">Play Again</button>
</template>
<script setup>
import { defineEmits } from "vue";
import useEasterEgg from "#/components/modules/wirdle_helpers/useEasterEgg.js";
useEasterEgg();
</script>
The error I get is "Uncaught TypeError: emit is not a function useEasterEgg.js:30:11
So obviously you can not use defineEmits in a .js file. I dont see anywhere in Vue docs where they specifically use this scenario. I dont see any other way to do this but using $emits but that is invoked in a template which my composable does not have. Any enlightenment much appreciated.
You can emit events from a composable, but it will need to know where the events should be fired from using context which can be accessed from the second prop passed to the setup function: https://vuejs.org/api/composition-api-setup.html#setup-context
Composable:
export default function useComposable(context) {
context.emit("some-event")
}
Component script:
<script>
import useComposable from "./useComposable"
export default {
emits: ["some-event"],
setup(props, context) {
useComposable(context)
}
}
</script>
To use it in a script setup, the best way I found was to declare the defineEmit first, and assigning it to a const, and pass it as a param to your composable :
const emit = defineEmit(['example']
useMyComposable(emit);
function useMyComposable(emit){
emit('example')
}
You can't access emit this way, as the doc says : defineProps and defineEmits are compiler macros only usable inside script setup. https://vuejs.org/api/sfc-script-setup.html
I'm not entirely sure of what you are trying to achieve but you can use vue-use composable library to listen to key strokes https://vueuse.org/core/onkeystroke/
Lx4
This question is a bit confusing. What is <uses-composable>? A composable generally is plan js/ts, with no template. If it had a template, it would just be a component. Even if it was a component, which I mean you could turn it into if thats what you wanted, I don't see anything there that suggests that would be a good idea.
So I guess the question is, why would you want to emit an event? If I'm following what you want, you can just do:
// inside useEasterEgg.js
document.addEventListener('keydown', () => {
// other code
const data = 'test';
updateStateCallback(data);
});
function useEasterEgg() {
function onUpdateState(callback) {
updateStateCallback = callback;
}
return {
onUpdateState,
}
}
// Put this wherever you want to listen to the event
const { onUpdateState } = useEasterEgg();
onUpdateState(data => console.log(data));
https://jsfiddle.net/tdfu3em1/3/
Alternatively, if you just want access to data, why not make it a ref and just use it where you want:
const data = ref();
document.addEventListener('keydown', () => {
// other code
data.value = resultOfOtherCode;
});
function useEasterEgg() {
return {
data,
}
}
// Anywhere you want to use it
const { data } = useEasterEgg();
I'm new to Vue.js 3, but I have a strange behavior accessing the “this” object in a component.
If my component is declared with the script setup, the access to “this” object is always undefined, see the below code:
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
console.info("Access KO: " + this)
})
</script>
If I use the export default, everything works fine, see the below code:
<script>
export default {
mounted() {
console.info("Access OK: " + JSON.stringify(this) + "<<")
}
}
</script>
Do you have any idea?
Thanks and regards.
Giuseppe
Arrow functions have a lexical this and its value within the arrow function is determined by the surrounding scope.In your case there is no surrounding scope.
that's the reason why we go with primitive functions.
Try the below code and see if this is working
<script setup>
import { onMounted } from 'vue';
onMounted() {
console.info("Access KO: " + this)
})
</script>
Note: There is nothing to do with export default. If you carefully observe, you are using primitive function in the second codeblock thatswhy its working.
onMounted uses callbacks, correct usage in this case should be like this
onMounted( () => console.info("Access KO: " + this))
The docs https://vuejs.org/guide/built-ins/suspense.html#async-components says in order to use Suspense Components, we need to make the components "Asynchronous".
<script setup>
const res = await fetch(...)
const posts = await res.json()
</script>
<template>
{{ posts }}
</template>
But I am not sure how to make components Async using Options API.
With the Options API, the component is made an async component by using an async setup():
export default {
👇
async setup() {
const res = await fetch(...)
const posts = await res.json()
return {
posts
}
}
}
That's actually documented just above the docs section the question links to.
demo
As the documentation states, only async setup function and asynchronous script setup are supported. Options API is legacy and isn't supposed to receive new features.
As it can be seen in source code, only setup is supported.
It may be possible to access internal component instance and follow the way setup works, e.g.:
beforeCreate() {
this.$.asyncDep = promise;
},
But this is undocumented and hacky way that can become broken without notice.
As far as I understand people are using server side rendering (ssr) to improve user experience and SEO with fast and content ready pages.
Recently I've started project with vue+nuxt in ssr mode.
What I've noticed is that when I try to prefetch data in nuxtServerInit action I have to wait for the async call to finish before page could be served to me.
As far as I know it will only hurt SEO and user experience.
export const actions = {
async nuxtServerInit ({ commit }) {
const response = await this.$axios.$get('games')
commit('setGameList', response.data)
}
}
Is there a way to actually prefetch data once and cache it for some period of time so that users would not be forced to wait?
Also what is the good usecase for nuxtServerInit? Cant understand the purpose of it..
Use The fetch Method
<template>
<h1>Stars: {{ $store.state.stars }}</h1>
</template>
<script>
export default {
async fetch ({ store, params }) {
let { data } = await axios.get('http://my-api/stars')
store.commit('setStars', data)
}
}
</script>
Remember to use Vuex to work well!
UPDATE: How to share the fetch function
1 - Create a file with the function:
// defaultFetch.js
module.exports = async function defaultFetch({ store, params }){
// Put some developer magic here to make the code works for you
let { data } = await axios.get('http://my-api/stars');
store.commit('setStars', data);
}
2 - Import and use in other components
// amazingComoponent1.vue
<template>
<h1>Stars: {{ $store.state.stars }}</h1>
</template>
<script>
import defaultFetch from "../utils/defaultFetch";
export default {
fetch: defaultFetch
}
</script>
// amazingComoponent2.vue
<template>
<h1>Stars: {{ $store.state.stars }}</h1>
</template>
<script>
import fetch from "../utils/defaultFetch";
export default {
fetch,
}
</script>
UPDATE 2: How to use and configure axios intance
Very easy, update the defaultFetch.js:
// defaultFetch.js
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
module.exports = async function defaultFetch({ store, params }){
// Put some developer magic here to make the code works for you
let { data } = await instance.get('http://my-api/stars');
store.commit('setStars', data);
}
Hope helps :)