Search code examples
vue.jsgeolocationvuejs3

Vue 3 Geolocation computed property latitude and longitude always returning 0


i create a composable function to get current coordinates from geolocation and returned correctly, but when i acces in my script setup always returned 0

here is my composable useGeolocation.js

import { onUnmounted, onMounted, ref } from 'vue'
export function useGeolocation(){
    const kordinat = ref({ latitude: 0, longitude: 0 })
    const isSupported = 'navigator' in window && 'geolocation' in navigator

    let watcher = null
    onMounted(() => {
        if(isSupported)
        watcher = navigator.geolocation.watchPosition(
            position => (kordinat.value = position.coords)
        )
    })

    onUnmounted(()=> {
        if (watcher) navigator.geolocation.clearWatch(watcher)
    })
    return { kordinat, isSupported }
}

and how I use in my component

<script setup>
import { useGeolocation } from '@/composables/useGeoLocation'
    const {kordinat} = useGeolocation()
    const posisiUser = computed(()=>({
        lat : kordinat.value.latitude,
        lng : kordinat.value.longitude
    }))
//...
</script>

in template i can display coordinates correctly with <h2>Coords : {{posisiUser.lat}}, {{posisiUser.lng}}</h2>

Coords : -6.22592, 106.8302336

but when i log console.log({p:posisiUser.value}) it returns '{"p":{"lat":0,"lng":0}}'

I need to be able access the correct coordinates for further usage. What is wrong?

here is sandbox link


Solution

  • You're logging the value of the computed prop immediately, which is not yet updated:

    <script setup>
    import { computed, ref, onMounted } from "vue";
    import { useGeolocation } from "./composables/useGeoLocation";
    
    const { kordinat } = useGeolocation();
    const posisiUser = computed(() => ({
      lat: kordinat.value.latitude,
      lng: kordinat.value.longitude,
    }));
    console.log({ p: posisiUser.value }); // ❌ posisiUser not yet updated in useGeolocation()
    </script>
    

    If you want to log every change to the value, you can use a watchEffect():

    watchEffect(() => {
      console.log({ p: posisiUser.value });
    })
    

    To watch it only once, you can do:

    const unwatch = watchEffect(() => {
      unwatch();
    
      console.log({ p: posisiUser.value });
    })
    

    demo