I have a reactivity confusion regarding toRaw().
App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <TheForm @newThing="addNewThing" />
  <TheList :allTheThings="allTheThings" />
</template>
<script setup>
  import TheForm from "./components/TheForm.vue";
  import TheList from "./components/TheList.vue";
  import { ref } from "vue";
  const allTheThings = ref([]);
  const addNewThing = (thing) => allTheThings.value.push(thing);
</script>
TheForm.vue
<template>
  <h3>Add New Thing</h3>
  <form @submit.prevent="addNewThing">
    <input type="text" placeholder="description" v-model="thing.desc" />
    <input type="number" placeholder="number" v-model="thing.number" />
    <button type="submit">Add New Thing</button>
  </form>
</template>
<script setup>
  import { reactive, defineEmit, toRaw } from "vue";
  const emit = defineEmit(["newThing"]);
  const thing = reactive({
    desc: "",
    number: 0,
  });
  const addNewThing = () => emit("newThing", thing);
</script>
TheList.vue
<template>
  <h3>The List</h3>
  <ol>
    <li v-for="(thing, idx) in allTheThings" :key="idx">
      {{ thing.desc }} || {{ thing.number }}
    </li>
  </ol>
</template>
<script setup>
  import { defineProps } from "vue";
  defineProps({
    allTheThings: Array,
  });
</script>
As the code is passing around proxies to the data, it acts as suspected: after submitting the form, if you re-edit the data in the form fields it also edits the output of the list. Fine.
So I want to pass in a non-reactive copy of thing in addNewThing:
  const addNewThing = () => {
    const clone = { ...thing };
    emit("newThing", clone);
  };
And it works as expected.
What doesn’t work is if I use const clone = toRaw(thing); instead.
If I log the output of each, { …thing} is EXACTLY the same as toRaw(thing) so why does toRaw() not seem to lose it’s reactivity?
Any light shone would be, well… enlightening.
I think the issue is that there is a misunderstanding of what toRaw does.
Returns the raw, original object of a
reactiveorreadonlyproxy. This is an escape hatch that can be used to temporarily read without incurring proxy access/tracking overhead or write without triggering changes. It is not recommended to hold a persistent reference to the original object. Use with caution.
toRaw will return the raw Proxy, not a copy of the contents of  the Proxy, so your solution to use const clone = { ...thing }; is IMHO appropriate, and hopefully this explanation is sufficient.
See similar question for more detail 👉 vue3 reactive unexpected behaviour
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With