I am trying to (deep) watch for any changes on a reactive object in Vue 3:
import { reactive, watchEffect } from 'vue';
const settings = reactive({
panes: {
left: {
defaultAction: "openInOtherPane",
},
right: {
defaultAction: "openInThisPane",
},
},
showMenu: false,
isDrawerOpen: false,
});
watchEffect(() => {
console.log('The new settings are', settings);
});
// Try to change a setting (this does not trigger watchEffect)
settings.panes.left.defaultAction = "none";
This code has two problems:
- The watchEffect is not triggered when settings are changed
- The console.log displays an unreadable object in the form of
Proxy { <target>: {…}, <handler>: {…} }
I also tried watch
:
watch(
() => settings,
settings => {
console.log('The new settings are', settings);
},
);
With the same problems.
When I only watch a property on the object, then it does work:
watchEffect(() => {
console.log('Is the menu shown:', settings.showMenu); // This works
});
And with destructuring I can watch changes one level deep, but not more levels:
watchEffect(() => {
// This works one level deep
console.log('Settings are changed:', { ...settings });
});
The settings can be logged using toRaw, but then the watchEffect is not triggered:
import { toRaw, watchEffect } from 'vue';
watchEffect(() => {
// console.log shows the raw object, but watchEffect is not triggered
console.log('Settings are changed:', toRaw(settings) );
});
Is there an elegant method to watch for changes on properties any level deep in a reactive object?