mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] store: ensure useStore proper clean up on destroy
This commit is contained in:
committed by
Géry Debongnie
parent
6c753bb49f
commit
a6f9b26057
+12
-6
@@ -84,6 +84,7 @@ const isStrictEqual = (a, b) => a === b;
|
||||
|
||||
export function useStore(selector, options: SelectorOptions = {}): any {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const componentId = component.__owl__.id;
|
||||
const store = options.store || (component.env.store as Store);
|
||||
if (!(store instanceof Store)) {
|
||||
throw new Error(`No store found when connecting '${component.constructor.name}'`);
|
||||
@@ -92,11 +93,10 @@ export function useStore(selector, options: SelectorOptions = {}): any {
|
||||
const hashFn = store.observer.revNumber.bind(store.observer);
|
||||
let revNumber = hashFn(result);
|
||||
const isEqual = options.isEqual || isStrictEqual;
|
||||
if (!store.updateFunctions[component.__owl__.id]) {
|
||||
store.updateFunctions[component.__owl__.id] = [];
|
||||
if (!store.updateFunctions[componentId]) {
|
||||
store.updateFunctions[componentId] = [];
|
||||
}
|
||||
const updateFunctions = store.updateFunctions[component.__owl__.id];
|
||||
updateFunctions.push(function(): boolean {
|
||||
store.updateFunctions[componentId].push(function(): boolean {
|
||||
const oldResult = result;
|
||||
result = selector(store!.state, component.props);
|
||||
const newRevNumber = hashFn(result);
|
||||
@@ -115,7 +115,7 @@ export function useStore(selector, options: SelectorOptions = {}): any {
|
||||
|
||||
useContextWithCB(store, component, function(): Promise<void> | void {
|
||||
let shouldRender = false;
|
||||
for (let fn of updateFunctions) {
|
||||
for (let fn of store.updateFunctions[componentId]) {
|
||||
shouldRender = fn() || shouldRender;
|
||||
}
|
||||
if (shouldRender) {
|
||||
@@ -123,9 +123,15 @@ export function useStore(selector, options: SelectorOptions = {}): any {
|
||||
}
|
||||
});
|
||||
onWillUpdateProps(props => {
|
||||
delete store.updateFunctions[component.__owl__.id];
|
||||
result = selector(store.state, props);
|
||||
});
|
||||
|
||||
const __destroy = component.__destroy;
|
||||
component.__destroy = parent => {
|
||||
delete store.updateFunctions[componentId];
|
||||
__destroy.call(component, parent);
|
||||
};
|
||||
|
||||
if (typeof result !== "object") {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -490,6 +490,25 @@ describe("connecting a component to store", () => {
|
||||
expect(fixture.innerHTML).toBe("<div><span>jupiler</span><span>kwak</span></div>");
|
||||
});
|
||||
|
||||
test("connected component is properly cleaned up on destroy", async () => {
|
||||
class App extends Component<any, any> {
|
||||
static template = xml`<div></div>`;
|
||||
state = useStore((state, props) => state);
|
||||
}
|
||||
|
||||
const store = new Store({ state: {} });
|
||||
(<any>env).store = store;
|
||||
const app = new App();
|
||||
|
||||
await app.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div></div>");
|
||||
expect(store.updateFunctions[app.__owl__.id].length).toBe(1);
|
||||
|
||||
app.destroy();
|
||||
|
||||
expect(store.updateFunctions[app.__owl__.id]).toBe(undefined);
|
||||
});
|
||||
|
||||
test("connected component with undefined, null and string props", async () => {
|
||||
class Beer extends Component<any, any> {
|
||||
static template = xml`
|
||||
|
||||
Reference in New Issue
Block a user