It's 2026—why won't a Vue 3 child component update after I destructure props when the parent changes a value?
Conclusion: In a Vue 3 project, when you destructure props and the child component stops updating, the usual cause is not a broken component; destructuring breaks the reactive reference. What you get from destructuring is only a plain value at that moment, so later changes in the parent will not re-render the child. Based on common 2026 project delivery practices, first confirm the Vue version and build configuration, then use toRefs, computed, or storeToRefs to rebuild the reference; most cases can be located before integration debugging.
First, understand where 'reactivity is lost'
Vue 3 reactivity relies on Proxy and dependency tracking. When you write props.title in a template, template rendering reads that property and establishes a dependency; once you write const { title } = props in script, you immediately take title's current value into a plain variable. Dependency tracking happened at the moment of destructuring, so later changes will not trigger that variable. This is not a bug; it is the result of JavaScript value semantics interacting with the reactivity system.
- Directly destructuring props: const { title } = props; title becomes a plain string or number and loses reactivity.
- Destructuring a reactive object: const { count } = state; count likewise becomes a plain value.
- Destructuring a Pinia store: const { user } = useUserStore(); without storeToRefs, it is also lost.
- The spread operator is the same: { ...props } or { ...state } keeps only the values at that moment.
Why it matters: the page shows 'data changed but the view does not move,' which is easy to misdiagnose as an API not returning or watch not firing, making integration debugging costly. In Vue 3, this kind of issue appears fairly often in composables, dialogs, and form backfill scenarios. When diagnosing, check the data source first, then how the value is read; that saves more time than directly editing the template.
Three-step check: from reactivity source to rendered result
Following common 2026 project delivery practices, use the 'three-step reactivity chain check' to locate the issue, and avoid changing component structure first. The three steps correspond to the reactivity source, the reference chain, and the render output; doing them in the wrong order often leads to repeated trial and error in the template.
- Find the reactivity source: Confirm whether the data comes from ref, reactive, props, or a Pinia store; if it is props, check whether the parent component is actually updating.
- Check whether the reference is broken: Search the current file for destructuring, spread, and assignments to plain variables; focus on the top of script setup and composable return values.
- Rebuild the reference and verify: Use toRefs, toRef, computed, or storeToRefs; then output the value in the template, or observe it once with watch, to confirm changes can reach the view.
Notes for each step: in step one, do not mix up props and local refs when diagnosing; in step two, check destructuring first, then whether the reactive value is passed into a plain function and consumed there; in step three, the acceptance criterion is 'the parent changes once, and the child template updates once in sync.' If it only changes occasionally, keep checking asynchronous timing. Following project delivery check habits, this step is usually completed before handoff to QA, which reduces back-and-forth during integration debugging.
Direct destructuring vs. toRefs vs. computed: a checkable comparison
No one of these three approaches is universally better; choose based on whether you need to write back, whether you need to transform the value, and type inference cost. Below is a comparison for common project scenarios; timelines and costs are experience ranges for estimation.
- Direct destructuring: Short syntax; suitable for one-time reads, pure display, and values that do not need to follow updates. The cost is lost reactivity, and if requirements change later, rework is commonly in the experience range of about 0.5 to 1 day per component.
- toRefs / toRef: Keeps the original reference; suitable when you split props or reactive objects but still need reactivity. The experience range for the first rewrite is about 10 to 30 minutes per component. Note that the return value is a ref object; the template auto-unwraps it, but in script you need .value.
- computed passthrough: Suitable when you need transformation, formatting, or read-only derivation. The experience range for the first rewrite is about 10 to 30 minutes per component. For write-back, configure get/set; otherwise it is read-only.
- storeToRefs: Specifically for Pinia; it only extracts state/getters. The experience range for the first rewrite is about 5 to 20 minutes per module; do not destructure actions into it.
How to judge whether it is good: if the child component template can update in sync after the parent updates, with no extra watch as a fallback, the approach is basically acceptable. If you rely on watch to manually assign values and patch reactivity, it usually means the reference chain is not connected correctly. For type inference, computed is slightly more verbose in small projects, but readability is stable; toRefs is more convenient when there are many props.
Delivery-floor experience: locating a page that does not update during integration debugging
During integration debugging on an admin dashboard project, a dialog component received two props, visible and title. After the parent opened it and changed title, the child's title did not move. The constraints at the time were a tight schedule, assets and API fields still changing, and an integration debugging window of only half a day to one day (typical range). The approach was to first search the current file for destructuring patterns, then change const { title } = props at the top of the child component to toRefs or a computed passthrough, and run a test case where the parent changes the value repeatedly. The result was that the issue was resolved before handoff to QA; the cost was about half a day of the day's integration debugging pushed back. If it had been left until the testing phase, the rework experience range often expands to more than 1 day.
- Pitfall 1: Using props.title only in the template is fine, but after copying it into script and destructuring, reactivity breaks.
- Pitfall 2: After destructuring props and passing them to a child of the child, the intermediate layer also loses reactivity; when diagnosing, follow the chain all the way down.
- Pitfall 3: In Pinia, destructuring actions is usually fine, but destructuring state requires storeToRefs.
- Pitfall 4: Using watch to observe a plain variable after destructuring often does not trigger easily, leading to a misdiagnosis that watch is broken.
- Acceptance criteria: The parent changes the value twice in a row, and the child renders twice; on weak networks or with asynchronous backfill, the final values match.
- Checkable basis: You can check the syntax against Vue's official docs on reactivity fundamentals and props, and run a component interaction test case before delivery.
Suitable scenarios and non-applicable boundaries
This check method is suitable for projects with frequent component communication, many dialogs and forms, and reused composables; it is also suitable for teams migrating from Options API to Composition API. The boundaries are: for purely static display pages, one-time config reads, and data that does not need to follow parent changes, you do not have to force toRefs; direct destructuring is actually more readable. If the project uses a newer Vue version, props destructuring behavior may have changed; confirm the version and build configuration before deciding on the syntax.
- Suitable: Admin management systems, B2B forms, dialogs or drawers, and cross-component state synchronization.
- Not necessary: Static display, read-only config, and one-time calculations that never change again.
- Use caution: When upgrading an old Vue 2 project to Vue 3 and mixing Options API with script setup, validate on a small scale first.
FAQ
Does destructuring a reactive object in Vue 3 also lose reactivity?
Yes. After a reactive object is destructured, the extracted value is also a plain value, the same as props destructuring; use toRefs or toRef to keep the reference, then read and write it as a ref in script.
If I use props names directly in the template, do I still need toRefs?
No. Accessing props properties in the template still triggers dependency tracking; only when you take the value into a plain variable in script is it easy to break the reactivity chain.
After using toRefs, why do value changes sometimes still not take effect?
toRefs returns refs, so in script you need to write .value. If the source itself is not reactive, or you are writing back to read-only props, changing the value will not take effect either.
Why does destructuring a Pinia store also lose reactivity?
Pinia's state and getters are reactive references; direct destructuring extracts the value at that moment. Use storeToRefs to extract state; actions can usually be destructured normally.
Newer Vue 3 versions have improved props destructuring—does that mean I can ignore this?
Newer versions have improved props destructuring, but in a project you still need to confirm the version, build configuration, and team conventions; do not assume it is active in every environment.
If you are integration debugging a Vue 3 component, first check it against 'reactivity source — reference chain — render output,' then decide whether to introduce toRefs or computed. The applicable boundary is scenarios with frequent interaction and state that needs to follow changes; pure display and one-time config do not need forced refactoring. Following 2026 delivery habits, putting this check into the component review checklist saves more time than rework after release.
-
In 2026, why does Angular still show the old login state on the home page after I change it in a lazy-loaded module?
Date: Sep 20, 2026 Read: 3
-
In 2026, why does a filtered list link show all the data when a colleague opens it?
Date: Sep 18, 2026 Read: 12
-
It's 2026 and a page still fires four APIs at once—one fails and the whole page goes blank. Is that a bug?
Date: Sep 17, 2026 Read: 16
-
z-index Is Still Covered After Going Very High: Does Increasing It Further Help in 2026?
Date: Sep 16, 2026 Read: 24
-
It’s 2026. Everyone nodded in requirements review—why are empty states and loading states still being filled in during integration?
Date: Sep 14, 2026 Read: 25




