From 21b85f1447be563ebf7eb557ebc882df11100cf6 Mon Sep 17 00:00:00 2001 From: linbudu599 Date: Tue, 18 Jul 2023 21:17:11 +0800 Subject: [PATCH] fix(appear): use copy of ref for valid ref value in useEffect cleanups --- packages/appear/src/typings.ts | 4 ++-- packages/appear/src/weex/index.tsx | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/appear/src/typings.ts b/packages/appear/src/typings.ts index bddb24c7e2..d65714c961 100644 --- a/packages/appear/src/typings.ts +++ b/packages/appear/src/typings.ts @@ -3,13 +3,13 @@ import type * as React from 'react'; export interface AppearProps { children: React.ReactElement; /** - * 元素进入可视区域触发的事件 + * Triggered when the element enters the visible area. * @param {CustomEvent} e * @returns {void} */ onAppear?: (e: CustomEvent) => void; /** - * 元素离开可视区域触发的事件 + * Triggered when the element leaves the visible area. * @param {CustomEvent} e * @returns {void} */ diff --git a/packages/appear/src/weex/index.tsx b/packages/appear/src/weex/index.tsx index 6f70319bd7..76410d3fd8 100644 --- a/packages/appear/src/weex/index.tsx +++ b/packages/appear/src/weex/index.tsx @@ -1,30 +1,30 @@ +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 childrenRef: ForwardedRef = ref ?? useRef(null); 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)); }; }, []); 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)); }; }, []);