From 5e819c27ee04e02593a0c6be55d08f423e50c07e Mon Sep 17 00:00:00 2001 From: LK is lake <61587068+yezhonghu0503@users.noreply.github.com> Date: Tue, 21 May 2024 16:41:03 +0800 Subject: [PATCH] fix: collapse component expands blank issue #6619 (#6627) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: collapse component expands blank issue #6619 * refactor: adjust logic * docs: rollback of demo --------- Co-authored-by: 二货机器人 --- src/components/collapse/collapse.tsx | 51 ++++++++++++++++--------- src/components/collapse/demos/demo1.tsx | 2 +- src/utils/use-mutation-effect.tsx | 35 ++++++++++++----- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/components/collapse/collapse.tsx b/src/components/collapse/collapse.tsx index 569cb3dc4a..816c5cf666 100644 --- a/src/components/collapse/collapse.tsx +++ b/src/components/collapse/collapse.tsx @@ -1,15 +1,16 @@ -import React, { isValidElement, useRef } from 'react' -import type { FC, ReactNode, ReactElement } from 'react' -import { NativeProps, withNativeProps } from '../../utils/native-props' -import List from '../list' +import { animated, useSpring } from '@react-spring/web' +import { useMount } from 'ahooks' import { DownOutline } from 'antd-mobile-icons' import classNames from 'classnames' -import { useSpring, animated } from '@react-spring/web' -import { usePropsValue } from '../../utils/use-props-value' -import { useMount } from 'ahooks' +import type { FC, ReactElement, ReactNode } from 'react' +import React, { isValidElement, useRef } from 'react' +import { NativeProps, withNativeProps } from '../../utils/native-props' import { useShouldRender } from '../../utils/should-render' -import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect' import { traverseReactNode } from '../../utils/traverse-react-node' +import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect' +import { observe } from '../../utils/use-mutation-effect' +import { usePropsValue } from '../../utils/use-props-value' +import List from '../list' const classPrefix = `adm-collapse` @@ -65,18 +66,32 @@ const CollapsePanelContent: FC<{ useIsomorphicUpdateLayoutEffect(() => { const inner = innerRef.current if (!inner) return + if (visible) { - api.start({ - height: inner.offsetHeight, - }) + let lastMotionId = 0 + let cancelObserve: VoidFunction = () => {} + + const handleMotion = () => { + lastMotionId += 1 + const motionId = lastMotionId + + api.start({ height: inner.offsetHeight })[0].then(() => { + if (motionId === lastMotionId) { + cancelObserve() + } + }) + } + + cancelObserve = observe( + inner, + { childList: true, subtree: true }, + handleMotion + ) + handleMotion() + return cancelObserve } else { - api.start({ - height: inner.offsetHeight, - immediate: true, - }) - api.start({ - height: 0, - }) + api.start({ height: inner.offsetHeight, immediate: true }) + api.start({ height: 0 }) } }, [visible]) diff --git a/src/components/collapse/demos/demo1.tsx b/src/components/collapse/demos/demo1.tsx index dc85fe56f2..ae2fbbab56 100644 --- a/src/components/collapse/demos/demo1.tsx +++ b/src/components/collapse/demos/demo1.tsx @@ -1,6 +1,6 @@ -import React from 'react' import { Collapse } from 'antd-mobile' import { DemoBlock, lorem } from 'demos' +import React from 'react' export default () => { return ( diff --git a/src/utils/use-mutation-effect.tsx b/src/utils/use-mutation-effect.tsx index 9c52efa25e..a9a9526d1d 100644 --- a/src/utils/use-mutation-effect.tsx +++ b/src/utils/use-mutation-effect.tsx @@ -1,5 +1,28 @@ -import { RefObject, useEffect } from 'react' import { useMemoizedFn } from 'ahooks' +import { RefObject, useEffect } from 'react' + +export function observe( + element: HTMLElement | null, + options: MutationObserverInit, + callback: VoidFunction +) { + if (element && typeof MutationObserver !== 'undefined') { + let observer: MutationObserver | null = new MutationObserver(() => { + callback() + }) + observer.observe(element, options) + + // Return cleanup function + return () => { + if (observer) { + observer.disconnect() + observer = null + } + } + } + + return () => {} +} export function useMutationEffect( effect: () => void, @@ -8,13 +31,7 @@ export function useMutationEffect( ) { const fn = useMemoizedFn(effect) useEffect(() => { - const observer = new MutationObserver(() => { - fn() - }) - if (!targetRef.current) return - observer.observe(targetRef.current, options) - return () => { - observer.disconnect() - } + const cleanup = observe(targetRef.current, options, fn) + return cleanup }, [targetRef]) }