The following example prints 1 then 2 in the console, but never 3.
The template does render 1 then 2 then 3 however.
We expect all read of this.props.o.val to be reactive in the same way, but it is not the case.
I understand the canonical way to proceed here would be to pass the signal as props instead of its return value.
But the example is still valid, and the inconsistency of props in terms of effect and rendering is highly problematic.
Because of this, onWillUpdateProps cannot be simply converted to equivalent useEffect, because callers need to provide a signal.
import { Component, mount, xml, props, types, useEffect, proxy, signal } from "@odoo/owl";
class Test extends Component {
static template = xml`<span t-out="this.props.o.val"/>`;
props = props(["o"]);
setup() {
useEffect(() => console.log(this.props.o.val));
}
}
class Root extends Component {
static template = xml`<div>Hello Owl!<Test o="this.obj()"/></div>`;
static components = { Test };
obj = signal(proxy({ val: 1 }));
setup() {
setTimeout(() => this.obj().val = 2, 100);
setTimeout(() => this.obj.set(proxy({ val: 3 })), 200);
}
}
mount(Root, document.body, { templates: TEMPLATES, dev: true });
Side remark, but I don't understand why props.signal="..." is not the default if the given value is not a signal. It seems extremely confusing and error prone to allow non-reactive values as props, but with just a little bit of magic to still trigger re-rendering. This is even more strange as .alike already exists for case where we would want to disable the auto-wrapping behavior.
The following example prints 1 then 2 in the console, but never 3.
The template does render 1 then 2 then 3 however.
We expect all read of
this.props.o.valto be reactive in the same way, but it is not the case.I understand the canonical way to proceed here would be to pass the signal as props instead of its return value.
But the example is still valid, and the inconsistency of props in terms of effect and rendering is highly problematic.
Because of this,
onWillUpdatePropscannot be simply converted to equivalentuseEffect, because callers need to provide a signal.Side remark, but I don't understand why
props.signal="..."is not the default if the given value is not a signal. It seems extremely confusing and error prone to allow non-reactive values as props, but with just a little bit of magic to still trigger re-rendering. This is even more strange as.alikealready exists for case where we would want to disable the auto-wrapping behavior.