diff --git a/src/core/HNode.ts b/src/core/HNode.ts
index 6469300..22422aa 100644
--- a/src/core/HNode.ts
+++ b/src/core/HNode.ts
@@ -27,15 +27,22 @@ export type HProps
= {
children: unknown[];
});
+export type HCallback
=
+ (this: HNode
, props: HProps
, store: S, context: C) => T;
+
+export type EffectCallback
=
+ HCallback
| void>;
+
export interface HDesc
{
defaultProps?: Partial
;
defaultStore?: Partial>;
storeHandlers?: PartialHandlers, S>;
+ effects?: EffectCallback[];
state?: Array>;
context?: Array>;
- init?: (this: HNode, props: HProps
, store: S, context: C) => void;
- render: (this: HNode
, props: HProps
, store: S, context: C) => unknown;
- clear?: (this: HNode
, props: HProps
, store: S, context: C) => void;
+ init?: HCallback
;
+ render: HCallback
;
+ clear?: HCallback
;
catch?: (this: HNode
, err: any, props: HProps
, store: S, context: C) => unknown;
}
@@ -52,6 +59,7 @@ export interface HNode
[];
err?: unknown;
}
diff --git a/src/core/HUI.ts b/src/core/HUI.ts
index b4fabe9..d9ac800 100644
--- a/src/core/HUI.ts
+++ b/src/core/HUI.ts
@@ -1,4 +1,4 @@
-import { HProps as _HProps, HDesc as _HDesc, HNode as _HNode } from "./HNode";
+import { HProps as _HProps, HDesc as _HDesc, HNode as _HNode, HCallback as _HCallback, EffectCallback as _EffectCallback } from "./HNode";
import { registry, define, HType as _HType } from "./registry";
import { _assign, _Infinity, _requestAnimationFrame } from "../utils/refCache";
import { Store as _Store, createStore, HandlerMap as _HandlerMap, Setter as _Setter, SetterRecord as _SetterRecord, StoreType as _StoreType, StoreHandlers as _StoreHandlers, PartialHandlers as _PartialHandlers, EmptyStore as _EmptyStore } from "./Store";
@@ -43,6 +43,8 @@ HUI.cmp = compare;
export namespace HUI {
export type HProps
= _HProps
;
+ export type HCallback
= _HCallback
;
+ export type EffectCallback
= _EffectCallback
;
export type HDesc
= _HDesc
;
export type HNode
= _HNode
;
diff --git a/src/core/initComponent.ts b/src/core/initComponent.ts
index 9aff5e9..53e1ee4 100644
--- a/src/core/initComponent.ts
+++ b/src/core/initComponent.ts
@@ -1,15 +1,16 @@
-import { HNode } from "./HNode";
+import { HNode, HCallback, HProps } from "./HNode";
import { Store } from "./Store";
import { supply } from "../utils/helpers";
+import { _Boolean } from "../utils/refCache";
-export const initComponent = function initCom(hNode: HNode, store: Store) {
+export const initComponent = function initCom(hNode: HNode
, store: S) {
const { props, ctx } = hNode,
desc = hNode.desc!,
- { defaultProps, defaultStore, storeHandlers, state, context, init } = desc;
+ { defaultProps, defaultStore, storeHandlers, state, context, init, effects } = desc;
if (defaultProps) {
- supply(props, defaultProps);
+ supply(props, defaultProps as Partial>);
}
hNode.sto = store;
@@ -17,18 +18,22 @@ export const initComponent = function initCom(hNode: HNode, store: Store) {
store.setSome(defaultStore);
}
if (state) {
- hNode.sto.bind(hNode, state);
+ hNode.sto.bind(hNode as unknown as HNode, state);
}
if (storeHandlers) {
store.handleSome(storeHandlers);
}
if (context) {
- ctx!.bind(hNode, context);
+ ctx!.bind(hNode as unknown as HNode, context);
}
if (init) {
init.call(hNode, props, store, ctx!);
}
+ if (effects) {
+ hNode.eff = effects.map(effect => effect.call(hNode, props, store, ctx!)).filter(_Boolean) as HCallback[];
+ }
+
};
\ No newline at end of file
diff --git a/src/ext/Portal.ts b/src/ext/Portal.ts
index 369dbcf..ed9712b 100644
--- a/src/ext/Portal.ts
+++ b/src/ext/Portal.ts
@@ -19,32 +19,39 @@ export interface PortalStore {
export const Portal = define, EmptyStore>('HUI.Portal', {
- init: function port_init(props, store) {
- store.set('p', props.parent || _document.body);
- store.set('f', HUI(Fragment, _null, props.children));
- },
+ effects: [
+ function ptl_eff(props, store) {
- render: function port_render(props, store, context) {
- renderToDOM(store.get('f'), {
- parent: store.get('p'),
- owner: this,
- context
- });
- },
+ const { parent = _document.body } = props,
+ fragment = HUI(Fragment, _null, props.children);
- clear: function port_clear(props, store) {
+ store.set('p', parent);
+ store.set('f', fragment);
- const fragment = store.get('f')!,
- { ownNode, nodes } = fragment;
+ return function ptl_clr() {
- clear(fragment);
+ const { ownNode, nodes } = fragment;
- nodes!.forEach(node => {
- ownNode!.removeChild(node);
- });
+ clear(fragment);
+
+ nodes!.forEach(node => {
+ ownNode!.removeChild(node);
+ });
+
+ nodes!.length = 0;
- nodes!.length = 0;
+ };
+ }
+ ],
+
+
+ render: function ptl_render(props, store, context) {
+ renderToDOM(store.get('f'), {
+ parent: store.get('p'),
+ owner: this,
+ context
+ });
}
});
diff --git a/src/utils/clear.ts b/src/utils/clear.ts
index 9812469..5ddfbe8 100644
--- a/src/utils/clear.ts
+++ b/src/utils/clear.ts
@@ -11,12 +11,22 @@ export const clear = function clr(hNode: HNode) {
if (desc) {
- if (desc.clear) {
- try {
- desc.clear.call(hNode, props, hNode.sto!, hNode.ctx!);
- } catch (err) {
- _console.error(err);
+ const { sto, ctx } = hNode;
+
+ try {
+
+ if (hNode.eff) {
+ hNode.eff.forEach(effCanceller => {
+ effCanceller.call(hNode, props, sto!, ctx!);
+ });
}
+
+ if (desc.clear) {
+ desc.clear.call(hNode, props, sto!, ctx!);
+ }
+
+ } catch (err) {
+ _console.error(err);
}
} else {
diff --git a/test/src/Timer.tsx b/test/src/Timer.tsx
index 0611b6e..89bf584 100644
--- a/test/src/Timer.tsx
+++ b/test/src/Timer.tsx
@@ -4,7 +4,6 @@ interface TimerProps {
interface TimerStore {
time: number;
- timer: any;
}
type TimerStoreHandlers = {
@@ -19,17 +18,24 @@ const Timer = HUI.define,
start: 0
},
+ effects: [
+ function (props, store) {
+ const timer = store.trigger('setInterval', 1000);
+ return () => {
+ clearInterval(timer);
+ };
+ }
+ ],
+
storeHandlers: {
setInterval(interval) {
const timer = setInterval(this.inc, interval, 'time');
- this.set('timer', timer);
return timer;
}
},
init(props, store) {
store.set('time', props.start!);
- store.set('timer', store.trigger('setInterval', 1000));
},
render(props, store) {
@@ -38,10 +44,6 @@ const Timer = HUI.define,
Time: {store.get('time')}
);
- },
-
- clear(props, store) {
- clearInterval(store.get('timer'));
}
});
\ No newline at end of file