mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] store: correct update order for child/parents
Not happy about the test, there was a bug in Discuss that is solved with this commit, but I could not reproduce it in a test. closes #85
This commit is contained in:
+36
-29
@@ -166,39 +166,46 @@ export function connect(mapStateToProps, options: any = {}) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
mounted() {
|
/**
|
||||||
this.env.store.on("update", this, () => {
|
* We do not use the mounted hook here for a subtle reason: we want the
|
||||||
const ownProps = this.__owl__.ownProps;
|
* updates to be called for the parents before the children. However,
|
||||||
const storeProps = mapStateToProps(this.env.store.state, ownProps);
|
* if we use the mounted hook, this will be done in the reverse order.
|
||||||
const options: any = {
|
*/
|
||||||
currentStoreProps: this.__owl__.currentStoreProps
|
_callMounted() {
|
||||||
};
|
this.env.store.on("update", this, this._checkUpdate);
|
||||||
const storeHash = hashFunction(
|
super._callMounted();
|
||||||
{
|
|
||||||
state: this.env.store.state,
|
|
||||||
storeProps: storeProps,
|
|
||||||
revNumber,
|
|
||||||
deepRevNumber
|
|
||||||
},
|
|
||||||
options
|
|
||||||
);
|
|
||||||
let didChange = options.didChange;
|
|
||||||
if (storeHash !== this.__owl__.storeHash) {
|
|
||||||
didChange = true;
|
|
||||||
this.__owl__.storeHash = storeHash;
|
|
||||||
}
|
|
||||||
if (didChange) {
|
|
||||||
this.__owl__.currentStoreProps = storeProps;
|
|
||||||
this._updateProps(ownProps, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
super.mounted();
|
|
||||||
}
|
}
|
||||||
willUnmount() {
|
willUnmount() {
|
||||||
this.env.store.off("update", this);
|
this.env.store.off("update", this);
|
||||||
super.willUnmount();
|
super.willUnmount();
|
||||||
}
|
}
|
||||||
_updateProps(nextProps, forceUpdate) {
|
|
||||||
|
_checkUpdate() {
|
||||||
|
const ownProps = this.__owl__.ownProps;
|
||||||
|
const storeProps = mapStateToProps(this.env.store.state, ownProps);
|
||||||
|
const options: any = {
|
||||||
|
currentStoreProps: this.__owl__.currentStoreProps
|
||||||
|
};
|
||||||
|
const storeHash = hashFunction(
|
||||||
|
{
|
||||||
|
state: this.env.store.state,
|
||||||
|
storeProps: storeProps,
|
||||||
|
revNumber,
|
||||||
|
deepRevNumber
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
let didChange = options.didChange;
|
||||||
|
if (storeHash !== this.__owl__.storeHash) {
|
||||||
|
didChange = true;
|
||||||
|
this.__owl__.storeHash = storeHash;
|
||||||
|
}
|
||||||
|
if (didChange) {
|
||||||
|
this.__owl__.currentStoreProps = storeProps;
|
||||||
|
this._updateProps(ownProps, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_updateProps(nextProps, forceUpdate, p?: any) {
|
||||||
if (this.__owl__.ownProps !== nextProps) {
|
if (this.__owl__.ownProps !== nextProps) {
|
||||||
this.__owl__.currentStoreProps = mapStateToProps(
|
this.__owl__.currentStoreProps = mapStateToProps(
|
||||||
this.env.store.state,
|
this.env.store.state,
|
||||||
@@ -211,7 +218,7 @@ export function connect(mapStateToProps, options: any = {}) {
|
|||||||
nextProps,
|
nextProps,
|
||||||
this.__owl__.currentStoreProps
|
this.__owl__.currentStoreProps
|
||||||
);
|
);
|
||||||
return super._updateProps(mergedProps, forceUpdate);
|
return super._updateProps(mergedProps, forceUpdate, p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -670,4 +670,48 @@ describe("connecting a component to store", () => {
|
|||||||
"<div><div><span>taster:matthieu</span><span>consumed:jupiler</span></div></div>"
|
"<div><div><span>taster:matthieu</span><span>consumed:jupiler</span></div></div>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("correct update order when parent/children are connected", async () => {
|
||||||
|
const steps: string[] = [];
|
||||||
|
class Parent extends Component<any, any, any> {
|
||||||
|
inlineTemplate = `
|
||||||
|
<div>
|
||||||
|
<t t-widget="Child" t-ref="'child'" t-props="{key: props.current}"/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
widgets = { Child: ConnectedChild };
|
||||||
|
}
|
||||||
|
const ConnectedParent = connect(function(s) {
|
||||||
|
steps.push("parent");
|
||||||
|
return { current: s.current, isvisible: s.isvisible };
|
||||||
|
})(Parent);
|
||||||
|
|
||||||
|
class Child extends Component<any, any, any> {
|
||||||
|
inlineTemplate = `<span><t t-esc="props.msg"/></span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConnectedChild = connect(function(s, props) {
|
||||||
|
steps.push("child");
|
||||||
|
return { msg: s.msg[props.key] };
|
||||||
|
})(Child);
|
||||||
|
|
||||||
|
const state = { current: "a", msg: { a: "a", b: "b" } };
|
||||||
|
const mutations = {
|
||||||
|
setCurrent({ state }, c) {
|
||||||
|
state.current = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = new Store({ state, mutations });
|
||||||
|
(<any>env).store = store;
|
||||||
|
const app = new ConnectedParent(env);
|
||||||
|
|
||||||
|
await app.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div><span>a</span></div>");
|
||||||
|
expect(steps).toEqual(["parent", "child"]);
|
||||||
|
|
||||||
|
store.commit("setCurrent", "b");
|
||||||
|
await nextTick();
|
||||||
|
expect(steps).toEqual(["parent", "child", "parent", "child", "child"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user