diff --git a/packages/appear/src/weex/index.tsx b/packages/appear/src/weex/index.tsx index 6f70319bd7..79af3c66f3 100644 --- a/packages/appear/src/weex/index.tsx +++ b/packages/appear/src/weex/index.tsx @@ -1,32 +1,34 @@ +import type { ForwardedRef } from 'react'; import { useEffect, useRef, forwardRef, cloneElement, Children } from 'react'; import type { AppearProps } from '../typings'; const WeexAppear = forwardRef((props, ref) => { - const childrenRef = ref || useRef(null); + const internalRef = useRef(null); + const childrenRef: ForwardedRef = ref ?? internalRef; + const { children, onAppear, onDisappear } = props; useEffect(() => { - onAppear && - typeof childrenRef === 'object' && - childrenRef.current?.addEventListener('appear', (e: CustomEvent) => onAppear(e)); + // Use copy of childrenRef to avoid ref value changed in cleanup phase. + const nodeRef = typeof childrenRef === 'object' ? childrenRef.current : null; + + // Return early if onAppear callback not specified. + onAppear && nodeRef?.addEventListener('appear', (e: CustomEvent) => onAppear(e)); + return () => { - onAppear && - typeof childrenRef === 'object' && - childrenRef.current?.removeEventListener('appear', (e: CustomEvent) => onAppear(e)); + onAppear && nodeRef?.removeEventListener('appear', (e: CustomEvent) => onAppear(e)); }; - }, []); + }, [childrenRef, onAppear]); useEffect(() => { - onDisappear && - typeof childrenRef === 'object' && - childrenRef.current?.addEventListener('disappear', (e: CustomEvent) => onDisappear(e)); + const nodeRef = typeof childrenRef === 'object' ? childrenRef.current : null; + + onDisappear && nodeRef?.addEventListener('disappear', (e: CustomEvent) => onDisappear(e)); return () => { - onDisappear && - typeof childrenRef === 'object' && - childrenRef.current?.removeEventListener('disappear', (e: CustomEvent) => onDisappear(e)); + onDisappear && nodeRef?.removeEventListener('disappear', (e: CustomEvent) => onDisappear(e)); }; - }, []); + }, [childrenRef, onDisappear]); return cloneElement(Children.only(children), { ref: childrenRef }); });