Home > Back-end >  How to unwrap data from nested props?
How to unwrap data from nested props?

Time:12-31

Why my variables after unwrapping from props stops being reactive?

I three components - parent, second for displaying and third for updating data depending on input (code is very simplified here).

Third component is updating parent via event and that updated value should be passed to child. I know that architecture might smell. I'm not using any store.

What I would expect is that emit is updating value and on Child1 new value is displayed. That happen if I do not unwrap unwrapped prop.

// Parent.vue
<template>
  <ChildA :data="data"/>
  <ChildB @update-data="updateData"/>
</template>
<script setup>
import { reactive, toRefs } from "vue";
const { data } = toRefs(
  reactive({ data: { latestEvent: { status: "fail" } } })
);

const updateData = (event) => {
  data.value = event;
};
</script>
// ChildA.vue
<template>
  {{ latestStatus }}
</template>
<script setup>
import { computed, toRefs } from "vue";

const props = defineProps({
  data: {
    type: Object,
    default: () => {},
  },
});
const { data } = toRefs(props);
const { latestEvent } = data.value;
const latestStatus = computed(() => data.value.latestEvent.status);
// const latestStatus = computed(() => latestEvent.status); THAT'S NOT REACTIVE
</script>
// ChildB.vue
<template>
  <select v-model="status" @change="onChange()">
    <option value="in progress">in progress</option>
    <option value="new">new</option>
    <option value="fail">fail</option>
  </select>
</template>
<script setup>
import { reactive, ref, toRefs } from "vue";
const status = ref("");
const emit = defineEmits(["updateData"]);

const onChange = () => {
  emit(
    "updateData",
    toRefs(
      reactive({
        latestEvent: { status: status },
      })
    )
  );
};
</script>

How to make my variables reactive after unwrapping from prop?

I would imagine something like this:

const { data } = toRefs(props);
const { latestEvent } = toRefs(data);

CodePudding user response:

Since the whole data and not just data.latestEvent.status value is changed, destructuring it early like const { latestEvent } = data.value disables the reactivity. latestEvent refers data.latestEvent object that exists at the time when setup function runs.

What happens here is basically:

let foo = { bar: { baz: 1 } };
let bar = foo.bar;
let baz = foo.bar.baz;
foo.bar = { baz: 2 };
console.log(bar !== foo.bar); // true
console.log(baz === 1); // true

It should always be:

const latestStatus = computed(() => data.value.latestEvent.status);
  • Related