From b8861dc4831943871a95cc53b6fd4accad788a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Tue, 17 Nov 2020 23:03:07 +0800 Subject: [PATCH] refactor: Replace BackTop with rc-motion (#27840) --- components/_util/reactNode.ts | 10 +++++++--- components/back-top/index.tsx | 30 ++++++++++++++++++------------ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/components/_util/reactNode.ts b/components/_util/reactNode.ts index ac7c97e1a6..872948d94f 100644 --- a/components/_util/reactNode.ts +++ b/components/_util/reactNode.ts @@ -2,16 +2,20 @@ import * as React from 'react'; export const { isValidElement } = React; +type AnyObject = Record; + +type RenderProps = undefined | AnyObject | ((originProps: AnyObject) => AnyObject | undefined); + export function replaceElement( element: React.ReactNode, replacement: React.ReactNode, - props: any, + props: RenderProps, ): React.ReactNode { if (!isValidElement(element)) return replacement; - return React.cloneElement(element, typeof props === 'function' ? props() : props); + return React.cloneElement(element, typeof props === 'function' ? props(element.props) : props); } -export function cloneElement(element: React.ReactNode, props?: any): React.ReactElement { +export function cloneElement(element: React.ReactNode, props?: RenderProps): React.ReactElement { return replaceElement(element, element, props) as React.ReactElement; } diff --git a/components/back-top/index.tsx b/components/back-top/index.tsx index 00f14a4935..9424004147 100644 --- a/components/back-top/index.tsx +++ b/components/back-top/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; -import Animate from 'rc-animate'; +import CSSMotion from 'rc-motion'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; +import useMergedState from 'rc-util/lib/hooks/useMergedState'; import classNames from 'classnames'; import omit from 'omit.js'; import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined'; @@ -8,6 +9,7 @@ import { throttleByAnimationFrame } from '../_util/throttleByAnimationFrame'; import { ConfigContext } from '../config-provider'; import getScroll from '../_util/getScroll'; import scrollTo from '../_util/scrollTo'; +import { cloneElement } from '../_util/reactNode'; export interface BackTopProps { visibilityHeight?: number; @@ -22,7 +24,9 @@ export interface BackTopProps { } const BackTop: React.FC = props => { - const [visible, setVisible] = React.useState(false); + const [visible, setVisible] = useMergedState(false, { + value: props.visible, + }); const ref = React.createRef(); const scrollEvent = React.useRef(); @@ -61,13 +65,6 @@ const BackTop: React.FC = props => { }; }, [props.target]); - const getVisible = () => { - if ('visible' in props) { - return props.visible; - } - return visible; - }; - const scrollToTop = (e: React.MouseEvent) => { const { onClick, target, duration = 450 } = props; scrollTo(0, { @@ -89,9 +86,18 @@ const BackTop: React.FC = props => { ); return ( - - {getVisible() ?
{children || defaultElement}
: null} -
+ + {({ className: motionClassName }) => { + const childNode = children || defaultElement; + return ( +
+ {cloneElement(childNode, ({ className }) => ({ + className: classNames(motionClassName, className), + }))} +
+ ); + }} +
); };