Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

watch a ref props object not take effect #10970

Closed
liruifengv opened this issue May 17, 2024 · 2 comments
Closed

watch a ref props object not take effect #10970

liruifengv opened this issue May 17, 2024 · 2 comments

Comments

@liruifengv
Copy link

liruifengv commented May 17, 2024

Vue version

3.4.21

Link to minimal reproduction

Playground reproduction

Steps to reproduce

  1. Create a Child.vue, define a props means propData, type is PropData
<template>
  <div>
      This is the child component
      <div>
          <div v-for="item in props.propData.head" :key="item">{{ item }}</div>
          <div v-for="item in props.propData.list" :key="item.Name">{{ item.Name }} - {{ item.Age }}</div>
      </div>
  </div>
</template>

<script setup lang="ts">
import { watch, isReactive, isRef, isProxy, isShallow } from 'vue';

export type PropData = {
  head: string[],
  list: Record<string, string>[]
}

const props = defineProps<{
  propData: PropData
}>()

watch(props.propData, (newVal) => {
}, {
  deep: true,
});
</script>
  1. In App.vue
<template>
  <main>
    <ChildComponent :propData="propData"/>
    <button @click="changeProps1">Change props 1</button>
    <button @click="changeProps2">Change props 2</button>
  </main>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ChildComponent, { type PropData } from './Child.vue'
const propData = ref<PropData>({
    head: [],
    list: [],
});
// change propData.value will not be watched by Child.vue
const changeProps1 = () => {
    propData.value = {
        head: ['Name', 'Age'],
        list: [
            { Name: 'John', Age: '25' },
            { Name: 'Jane', Age: '22' },
        ],
    };
}
// change propData.value.list will be watched by Child.vue
const changeProps2 = () => {
    propData.value.head = ['Name', 'Age'];
    propData.value.list = [
        { Name: 'John', Age: '30' },
        { Name: 'liruifengv', Age: '18' },
    ];
}
</script>

<style scoped>
</style>
  1. When changed the propData.value, child component watch(props.propData) will not watch it change.
    But template rerender correctly. and watch a getter watch(()=>props.propData) will take effect.

What is expected?

When propData changed, watch(props.propData) will watched this change, same as tamplate rerender and watch(()=>props.propData)

What is actually happening?

  • When propData changed, watch(props.propData) not take effect.

  • When clicked the changeProps1 button,then click changeProps2 will also invalid

System Info

No response

Any additional comments?

No response

@liuhanqu
Copy link

watch( () => props.propData, () => {})

props.propsData is not ref.

@CGQAQ
Copy link

CGQAQ commented May 17, 2024

https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiWatch.ts#L241-L281

if (isRef(source)) {
    getter = () => source.value
    forceTrigger = isShallow(source)
  } else if (isReactive(source)) {
    getter = () => reactiveGetter(source)
    forceTrigger = true
  } else if (isArray(source)) {
    isMultiSource = true
    forceTrigger = source.some(s => isReactive(s) || isShallow(s))
    getter = () =>
      source.map(s => {
        if (isRef(s)) {
          return s.value
        } else if (isReactive(s)) {
          return reactiveGetter(s)
        } else if (isFunction(s)) {
          return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER)
        } else {
          __DEV__ && warnInvalidSource(s)
        }
      })
  } else if (isFunction(source)) {
    if (cb) {
      // getter with cb
      getter = () =>
        callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER)

But I saw it will all convert to getter anyway, is there anything I missed?

@github-actions github-actions bot locked and limited conversation to collaborators Jun 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants