diff --git a/packages/runtime/src/components/_internal/ModuleRenderer.tsx b/packages/runtime/src/components/_internal/ModuleRenderer.tsx index ca4281d7..b3c63551 100644 --- a/packages/runtime/src/components/_internal/ModuleRenderer.tsx +++ b/packages/runtime/src/components/_internal/ModuleRenderer.tsx @@ -18,42 +18,40 @@ type Props = Static & { export const ModuleRenderer: React.FC = props => { const { type, properties, handlers, evalScope, services, app } = props; - // first eval the property of module - const { - properties: moduleProperties, - handlers: moduleHandlers, - moduleId, - } = services.stateManager.mapValuesDeep( - { properties, handlers, moduleId: props.id }, - ({ value }) => { + function evalObject>( + obj: T, + scope?: Record + ): T { + return services.stateManager.mapValuesDeep({ obj }, ({ value }) => { if (typeof value === 'string') { - return services.stateManager.maskedEval(value, true, evalScope); + return services.stateManager.maskedEval(value, true, scope || evalScope); } return value; - } - ); + }).obj; + } - const runtimeModule = services.registry.getModuleByType(type); - const parsedtemplete = runtimeModule.spec.components.map(parseTypeComponents); + // first eval the property, handlers, id of module + // TODO: maybe can useMemo here + const moduleId = services.stateManager.maskedEval(props.id, true, evalScope); + const evaledProperties = evalObject(properties); + const evaledHanlders = evalObject(handlers); + + const moduleSpec = services.registry.getModuleByType(type); + const parsedtemplete = moduleSpec.spec.components.map(parseTypeComponents); + const moduleInnerScope = { + ...evaledProperties, + $moduleId: moduleId, + }; // then eval the template and stateMap of module - const { parsedtemplete: evaledModuleTemplate, stateMap: evaledStateMap } = - services.stateManager.mapValuesDeep( - { parsedtemplete, stateMap: runtimeModule.spec.stateMap }, - ({ value }) => { - if (typeof value === 'string') { - return services.stateManager.maskedEval(value, true, { - ...moduleProperties, - $moduleId: moduleId, - }); - } - return value; - } - ); + const evaledModuleTemplate = evalObject(parsedtemplete, moduleInnerScope); + const evaledStateMap = evalObject(moduleSpec.spec.stateMap, moduleInnerScope); // listen component state change useEffect(() => { if (!evaledStateMap) return; + const stops: ReturnType[] = []; + for (const stateKey in evaledStateMap) { const stop = watch( () => { @@ -68,6 +66,7 @@ export const ModuleRenderer: React.FC = props => { ); stops.push(stop); } + return () => { stops.forEach(s => s()); }; @@ -75,8 +74,8 @@ export const ModuleRenderer: React.FC = props => { // listen module event useEffect(() => { - if (!moduleHandlers) return; - const _handlers = moduleHandlers as Array>; + if (!evaledHanlders) return; + const _handlers = evaledHanlders as Array>; const moduleEventHanlders: any[] = []; _handlers.forEach(h => { const moduleEventHanlder = ({ fromId, eventType }: Record) => { @@ -97,7 +96,7 @@ export const ModuleRenderer: React.FC = props => { services.apiService.off('moduleEvent', h); }); }; - }, [moduleHandlers]); + }, [evaledHanlders]); const { topLevelComponents, slotComponentsMap } = resolveAppComponents( evaledModuleTemplate,