rahulserver
rahulserver

Reputation: 11205

Vue 3 get value of a proxy

Here is my RequestList.vue component

<template>
  <ion-item v-for="request in requests" @click="showRequest(request)" :key="request.id"
            text-wrap>
    <ion-label>
      <b>Name:</b> {{ request.event.name }}
      <br>
      <b>Venue:</b>{{ request.event.venue.name }}
      <br>
      <b>Date:</b> {{ request.event.date }}
    </ion-label>
  </ion-item>
</template>

<script>
import {useRouter} from 'vue-router'
import {IonItem, IonLabel} from '@ionic/vue'
import store from '@/store';
export default {
  components: {
    IonLabel,
    IonItem
  },
  props: {
    requests: Array
  },
  setup(props) {
    const router = useRouter()
    const showRequest= (request)=> {
      console.log('request', props.request);
      store.requests.setRequest(props.requests);
    };
    return {router, showRequest}
  }
}
</script>

My store/modules/requests.js file

import {computed, ref} from "vue";

const state = ref({
  request: null
});

export function setRequest(request) {
  state.value.request = request;
}

export const getRequest = computed(() => state.value.request);

My Requests.vue component where I am using the RequestList.vue

<template>
  <ion-page>
    <ion-header>
      <ion-toolbar></ion-toolbar>
    </ion-header>
    <ion-content class="ion-padding-start ion-padding-end">
      <ion-list-header>
        <ion-label>
          <b>Requests</b>
        </ion-label>
      </ion-list-header>
      <div v-if="!loading">
        <request-list :requests="requests" />
      </div>
      <div v-else>
        <ion-spinner class="spin"></ion-spinner>
      </div>
    </ion-content>
  </ion-page>
</template>

<script>
import { defineComponent } from 'vue'
import { IonContent, IonHeader, IonLabel, IonListHeader, IonPage, IonSpinner, IonToolbar } from '@ionic/vue'
import { reactive, toRefs } from '@vue/reactivity'
import { onMounted } from '@vue/runtime-core'
import RequestList from '../components/RequestList'
import firestoreService from '@/services/firestore'

export default defineComponent({
  components: {
    IonContent,
    IonPage,
    IonLabel,
    IonHeader,
    IonSpinner,
    IonToolbar,
    IonListHeader,
    RequestList
  },
  setup() {
    const state = reactive({
      requests: [],
      loading: false
    })

    onMounted(async () => {
      state.loading = true
      try {
        state.requests = await firestoreService.getClaimableRequestsForCurrentUser()
      } catch (e) {
        console.log('error occurred fetching requests for current user', e)
      } finally {
        state.loading = false
      }
    })
    return {
      ...toRefs(state),
    }
  }
})
</script>

My issue is that in RequestList.vue above, the showRequest handler is sending request as param which is a proxy. And thats why the store.requests.setRequest(props.requests) is setting a proxy in the store. Whereas I need the value of props.requests.

So how do I do it here?

Upvotes: 29

Views: 44739

Answers (3)

hermeslm
hermeslm

Reputation: 1990

There are different ways to get the raw value of a proxy:

1. (My Recommended way) Vue 3 Reactivity utils functions, see Reactivity API:

import { isProxy, toRaw } from 'vue';
if(isProxy(proxyObject)){ //this If() block is not really necessary
  const rawObject = toRaw(proxyObject)
}
//But it is not recommended to hold a persistent reference to the original object. Use with caution.

2. Using JSON stringify/parse:

const rawObject = JSON.parse(JSON.stringify(proxyObject));

3. Destructuring:

const rawObject = {...proxyObject};

4. Object.assign:

const rawObject = Object.assign({}, proxyObject);

Upvotes: 60

ktm5124
ktm5124

Reputation: 12123

You can often get the value of a Proxy object using the toString() method.

const { createApp } = Vue

createApp({
    data() {
        return {
            var: "hello world"
        }
    }, 
    mounted() {
        if (var.toString() == "hello world") {
            alert("Success");
        }
    }
}).mount("#app");

You can also use the toRaw method, but this method has to be imported. The toString method does not have to be imported, so it's often simplest.

Upvotes: -2

Daniel
Daniel

Reputation: 35714

The easiest way may be to use JSON stringify/parse

    const showRequest = (request)=> {
      const reqObject = JSON.parse(JSON.stringify(request));
      console.log('request', reqObject);
      store.requests.setRequest(reqObject);
    };

Destructuring ({..request} or Object.assign({}, request)) ) sometimes works too, but only if you've got a single level of proxies, whereas the stringify/parse will work on the entire object (just make sure you don't have any cyclic object values.

Upvotes: 5

Related Questions