add HiddenImplWrapper

This commit is contained in:
Bowen Tan 2022-04-24 17:13:05 +08:00
parent 869937dfbd
commit 0da51400bc
9 changed files with 122 additions and 3 deletions

View File

@ -0,0 +1,43 @@
import React, { useEffect, useMemo, useState } from 'react';
import { ImplWrapperProps, TraitResult } from '../../../types';
import { ImplWrapperMain } from './ImplWrapperMain';
import { useRuntimeFunctions } from './hooks/useRuntimeFunctions';
export const HiddenImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
(props, ref) => {
const { component: c, services } = props;
const { stateManager } = services;
const { executeTrait } = useRuntimeFunctions(props);
const hiddenTraits = useMemo(
() => c.traits.filter(t => t.type === 'core/v1/hidden'),
[c.traits]
);
const [isHidden, setIsHidden] = useState(() => {
const results: TraitResult<string, string>[] = hiddenTraits.map(t => {
const properties = stateManager.deepEval(t.properties);
return executeTrait(t, properties);
});
return results.some(result => result.unmount);
});
useEffect(() => {
if (hiddenTraits.length > 0) {
hiddenTraits.map(t => {
const properties = stateManager.deepEvalAndWatch(t.properties, newV => {
console.log('get hidden results', newV.result.hidden);
const result = executeTrait(t, newV.result);
setIsHidden(!!result.unmount);
if (result.unmount) {
// // Every component's state is initialize in initStateAnd Method.
// // So if if it should not render, we should remove it from store.
delete stateManager.store[c.id];
}
});
return executeTrait(t, properties);
});
}
}, [c, executeTrait, hiddenTraits, stateManager]);
return !isHidden ? <ImplWrapperMain {...props} ref={ref} /> : null;
}
);

View File

@ -2,6 +2,17 @@ import React from 'react';
import { ImplWrapperProps } from '../../../types';
import { shallowCompareArray } from '../../../utils/shallowCompareArray';
import { ImplWrapperMain } from './ImplWrapperMain';
// import { HiddenImplWrapper } from './HiddenImplWrapper';
// export const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
// (props, ref) => {
// return (
// <HiddenImplWrapper {...props}>
// <ImplWrapperMain {...props} ref={ref} />
// </HiddenImplWrapper>
// );
// }
// );
export const ImplWrapper = React.memo<ImplWrapperProps>(
ImplWrapperMain,

View File

@ -12,6 +12,7 @@ import { useGridLayout } from './hooks/useGridLayout';
export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
(props, ref) => {
const { component: c, children } = props;
console.info('####ImplWrapper Render', c.id);
const { registry, stateManager } = props.services;
const Impl = registry.getComponent(c.parsedType.version, c.parsedType.name).impl;
@ -36,12 +37,14 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
// eval traits' properties then execute traits
useEffect(() => {
console.log('开始监听 trait 表达式变化', c.id);
const stops: ReturnType<typeof watch>[] = [];
const properties: Array<RuntimeTraitSchema['properties']> = [];
c.traits.forEach((t, i) => {
const { result, stop } = stateManager.deepEvalAndWatch(
t.properties,
({ result: property }: any) => {
console.log('trait变了', t.type, property);
const traitResult = executeTrait(t, property);
setTraitResults(oldResults => {
// assume traits number and order will not change
@ -101,6 +104,7 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
}, [c.properties, stateManager]);
useEffect(() => {
console.info('####Component DidMount', c.id);
const clearFunctions = propsFromTraits?.componentDidMount?.map(e => e());
return () => {
clearFunctions?.forEach(func => func && func());
@ -109,6 +113,7 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
}, []);
useDidUpdate(() => {
console.info('####Component Update', c.id);
const clearFunctions = propsFromTraits?.componentDidUpdate?.map(e => e());
return () => {
clearFunctions?.forEach(func => func && func());
@ -116,6 +121,11 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
});
useDidUnmount(() => {
console.info(
'####Component DidUnmount',
c.id,
propsFromTraits?.componentDidUnmount
);
propsFromTraits?.componentDidUnmount?.forEach(e => e());
});

View File

@ -15,11 +15,13 @@ export function useEleRef(props: ImplWrapperProps) {
};
useEffect(() => {
console.info('####ImplWrapper DidMount', c.id);
// If a component is in module, it should not have mask, so we needn't set it
if (eleRef.current && !isInModule) {
eleMap.set(c.id, eleRef.current);
}
return () => {
console.info('####ImplWrapper DidUnmount', c.id);
if (!isInModule) {
eleMap.delete(c.id);
}

View File

@ -24,6 +24,7 @@ export function useRuntimeFunctions(props: ImplWrapperProps) {
const executeTrait = useCallback(
(trait: RuntimeTraitSchema, traitProperty: RuntimeTraitSchema['properties']) => {
console.log('执行了trait', trait.type);
const tImpl = registry.getTrait(
trait.parsedType.version,
trait.parsedType.name

View File

@ -37,6 +37,34 @@ export default implementRuntimeComponent({
styleSlots: ['content'],
events: [],
},
})(({ value, customStyle, elementRef }) => {
return <_Text value={value} cssStyle={customStyle?.content} ref={elementRef} />;
});
})(
({
value,
customStyle,
elementRef,
// component,
// componentDidMount,
// componentDidUnmount,
// componentDidUpdate,
}) => {
// console.info('####Component Render', component.id);
// useEffect(() => {
// console.info('####Component DidMount', component.id);
// componentDidMount?.forEach(e => e());
// }, [component.id, componentDidMount]);
// useEffect(() => {
// console.info('####Component Update', component.id);
// componentDidUpdate?.forEach(e => e());
// }, [component.id, componentDidMount, componentDidUpdate]);
// useEffect(() => {
// return () => {
// console.info('Component DidUnmount', component.id, componentDidUnmount);
// componentDidUnmount?.forEach(e => e());
// };
// }, [component.id, componentDidUnmount]);
return <_Text value={value} cssStyle={customStyle?.content} ref={elementRef} />;
}
);
// 不知道为什么计时器还在继续貌似是因为style执行了两次两个interval但是clear只执行了一次
// 另一个问题是为什么style会执行两次呢

View File

@ -28,6 +28,7 @@ const FetchTraitFactory: TraitImplFactory<Static<typeof FetchTraitPropertiesSpec
const lazy = _lazy === undefined ? true : _lazy;
const fetchData = () => {
console.log('fetch body', body);
if (disabled) return;
// TODO: clear when component destroy
// FIXME: listen to the header change

View File

@ -28,6 +28,7 @@ const StateTraitFactory: TraitImplFactory<Static<typeof PropsSpec>> = () => {
props: {
componentDidMount: [
() => {
console.log('merge state');
mergeState({ [key]: initialValue });
},
],

View File

@ -8,9 +8,31 @@ const StyleTraitFactory: TraitImplFactory<Static<typeof PropsSpec>> = () => {
styles.forEach(style => {
customStyle[style.styleSlot] = style.style;
});
let interval: ReturnType<typeof setInterval> | undefined;
return {
props: {
customStyle,
componentDidMount: [
() => {
if (interval) {
clearInterval(interval);
}
interval = setInterval(() => {
console.log(2333, customStyle.content);
}, 1000);
console.log('开始计时', interval);
},
],
componentDidUpdate: [],
componentDidUnmount: [
() => {
console.log('停止计时', interval);
if (interval) {
clearInterval(interval);
interval = undefined;
}
},
],
},
};
};