Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Vue3, how to convert Nested Proxy Objects (Reactive data) to regular objects?

I have a pinia store that has a user object..

export const useStore = defineStore('store', {
  state: () => ({
    currentSlide: 1,
    user: {},
    data,
  }),
})

I am then updating it to have a an array vote inside the user object

And then the vote array has multiple objects as votes.. so I have the array as a user.vote which then is in this format [{vote:01},{vote:02}.{vote:3}]

I need to push this array to mongodb.. but when I try to access this array, as it's reactive data, it's a Proxy Object with multiple Proxy Objects inside of it..

So I tried toRaw(user.vote) (not sure if this is the right approach) and the array was no longer a Proxy but a regular array.. however the objects (votes) inside of it are still Proxy Objects..

How do I get a regular array with regular objects from this pinia structure to send to mongodb?

like image 308
Alim Bolar Avatar asked Jul 30 '26 21:07

Alim Bolar


2 Answers

TypeScript version:

import { isReactive, toRaw } from 'vue'

export function isObject (value: unknown): boolean {
  return value !== null && !Array.isArray(value) && typeof value === 'object'
}

export function getRawData<T>(data: T): T {
  return isReactive(data) ? toRaw(data) : data
}

export function toDeepRaw<T>(data: T): T {
  const rawData = getRawData<T>(data)

  for (const key in rawData) {
    const value = rawData[key]

    if (!isObject(value) && !Array.isArray(value)) {
      continue
    }

    rawData[key] = toDeepRaw<typeof value>(value)
  }

  return rawData // much better: structuredClone(rawData)
}

JavaScript version:

import { isReactive, toRaw } from 'vue'

export function isObject (value) {
  return value !== null && !Array.isArray(value) && typeof value === 'object'
}

export function getRawData (data) {
  return isReactive(data) ? toRaw(data) : data
}

export function toDeepRaw (data) {
  const rawData = getRawData(data)

  for (const key in rawData) {
    const value = rawData[key]

    if (!isObject(value) && !Array.isArray(value)) {
      continue
    }

    rawData[key] = toDeepRaw(value)
  }

  return rawData // much better: structuredClone(rawData)
}

with Nuxt.js 3, add these helpers in a file to the utils/ folder for auto-imports.

like image 114
bgrand-ch Avatar answered Aug 02 '26 12:08

bgrand-ch


What if you clone the data and send the clone to the DB? That's what I usually do:

const cloneToSendToMongoDB = JSON.parse(JSON.stringify(user.vote)

or use lodash cloneDeep which is a little more readable than above:

// install lodash if you don't have it
import cloneDeep from 'lodash/cloneDeep' 

const cloneToSendToMongoDB = cloneDeep(user.vote)

Warning: Don't get excited and think, oh we are cloning stuff, so I can use the cool new structuredClone method for this, it will not unwrap the nested proxies unfortunately, only the outermost proxy. The first two methods above will unwrap everything.

like image 44
Stephen Studer Avatar answered Aug 02 '26 11:08

Stephen Studer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!