From 2d9f7de5247dad57c39e4b4268f9d944d2441ab7 Mon Sep 17 00:00:00 2001 From: lijianan <574980606@qq.com> Date: Tue, 11 Jul 2023 23:01:17 +0800 Subject: [PATCH] chore: code style optimization (#43478) * chore: code style optimization * add type --- components/alert/Alert.tsx | 62 +++--- components/carousel/index.tsx | 162 ++++++++-------- components/checkbox/Group.tsx | 74 +++---- components/dropdown/dropdown.tsx | 2 +- components/layout/Sider.tsx | 291 +++++++++++++--------------- components/popconfirm/PurePanel.tsx | 7 +- components/transfer/ListItem.tsx | 9 +- 7 files changed, 293 insertions(+), 314 deletions(-) diff --git a/components/alert/Alert.tsx b/components/alert/Alert.tsx index 42419f8e4a..20a416c8e8 100644 --- a/components/alert/Alert.tsx +++ b/components/alert/Alert.tsx @@ -96,25 +96,27 @@ const CloseIcon: React.FC = (props) => { ) : null; }; -const Alert: React.FC = ({ - description, - prefixCls: customizePrefixCls, - message, - banner, - className, - rootClassName, - style, - onMouseEnter, - onMouseLeave, - onClick, - afterClose, - showIcon, - closable, - closeText, - closeIcon, - action, - ...props -}) => { +const Alert: React.FC = (props) => { + const { + description, + prefixCls: customizePrefixCls, + message, + banner, + className, + rootClassName, + style, + onMouseEnter, + onMouseLeave, + onClick, + afterClose, + showIcon, + closable, + closeText, + closeIcon, + action, + ...otherProps + } = props; + const [closed, setClosed] = React.useState(false); if (process.env.NODE_ENV !== 'production') { warning(!closeText, 'Alert', '`closeText` is deprecated. Please use `closeIcon` instead.'); @@ -129,14 +131,13 @@ const Alert: React.FC = ({ props.onClose?.(e); }; - const getType = () => { - const { type } = props; - if (type !== undefined) { - return type; + const type = React.useMemo(() => { + if (props.type !== undefined) { + return props.type; } // banner mode defaults to 'warning' return banner ? 'warning' : 'info'; - }; + }, [props.type, banner]); // closeable when closeText or closeIcon is assigned const isClosable = React.useMemo(() => { @@ -150,8 +151,6 @@ const Alert: React.FC = ({ return closeIcon !== false && closeIcon !== null && closeIcon !== undefined; }, [closeText, closeIcon, closable]); - const type = getType(); - // banner mode defaults to Icon const isShowIcon = banner && showIcon === undefined ? true : showIcon; @@ -170,10 +169,7 @@ const Alert: React.FC = ({ hashId, ); - const dataOrAriaProps = pickAttrs(props, { - aria: true, - data: true, - }); + const restProps = pickAttrs(otherProps, { aria: true, data: true }); return wrapSSR( = ({ motionName={`${prefixCls}-motion`} motionAppear={false} motionEnter={false} - onLeaveStart={(node) => ({ - maxHeight: node.offsetHeight, - })} + onLeaveStart={(node) => ({ maxHeight: node.offsetHeight })} onLeaveEnd={afterClose} > {({ className: motionClassName, style: motionStyle }) => ( @@ -196,7 +190,7 @@ const Alert: React.FC = ({ onMouseLeave={onMouseLeave} onClick={onClick} role="alert" - {...dataOrAriaProps} + {...restProps} > {isShowIcon ? ( ( - ( - { - dots = true, - arrows = false, - draggable = false, - waitForAnimate = false, - dotPosition = 'bottom', - vertical = dotPosition === 'left' || dotPosition === 'right', - rootClassName, - className: customClassName, - style, - ...props - }, +const Carousel = React.forwardRef((props, ref) => { + const { + dots = true, + arrows = false, + draggable = false, + waitForAnimate = false, + dotPosition = 'bottom', + vertical = dotPosition === 'left' || dotPosition === 'right', + rootClassName, + className: customClassName, + style, + ...otherProps + } = props; + const { getPrefixCls, direction, carousel } = React.useContext(ConfigContext); + const slickRef = React.useRef(); + + const goTo = (slide: number, dontAnimate = false) => { + slickRef.current.slickGoTo(slide, dontAnimate); + }; + + React.useImperativeHandle( ref, - ) => { - const { getPrefixCls, direction, carousel } = React.useContext(ConfigContext); - const slickRef = React.useRef(); + () => ({ + goTo, + autoPlay: slickRef.current.innerSlider.autoPlay, + innerSlider: slickRef.current.innerSlider, + prev: slickRef.current.slickPrev, + next: slickRef.current.slickNext, + }), + [slickRef.current], + ); - const goTo = (slide: number, dontAnimate = false) => { - slickRef.current.slickGoTo(slide, dontAnimate); - }; + const prevCount = React.useRef(React.Children.count(props.children)); - React.useImperativeHandle( - ref, - () => ({ - goTo, - autoPlay: slickRef.current.innerSlider.autoPlay, - innerSlider: slickRef.current.innerSlider, - prev: slickRef.current.slickPrev, - next: slickRef.current.slickNext, - }), - [slickRef.current], - ); - - const prevCount = React.useRef(React.Children.count(props.children)); - - React.useEffect(() => { - if (prevCount.current !== React.Children.count(props.children)) { - goTo(props.initialSlide || 0, false); - prevCount.current = React.Children.count(props.children); - } - }, [props.children]); - - const newProps = { - vertical, - className: classNames(customClassName, carousel?.className), - style: { ...carousel?.style, ...style }, - ...props, - }; - - if (newProps.effect === 'fade') { - newProps.fade = true; + React.useEffect(() => { + if (prevCount.current !== React.Children.count(props.children)) { + goTo(props.initialSlide || 0, false); + prevCount.current = React.Children.count(props.children); } + }, [props.children]); - const prefixCls = getPrefixCls('carousel', newProps.prefixCls); - const dotsClass = 'slick-dots'; + const newProps = { + vertical, + className: classNames(customClassName, carousel?.className), + style: { ...carousel?.style, ...style }, + ...otherProps, + }; - const enableDots = !!dots; - const dsClass = classNames( - dotsClass, - `${dotsClass}-${dotPosition}`, - typeof dots === 'boolean' ? false : dots?.className, - ); + if (newProps.effect === 'fade') { + newProps.fade = true; + } - const [wrapSSR, hashId] = useStyle(prefixCls); + const prefixCls = getPrefixCls('carousel', newProps.prefixCls); + const dotsClass = 'slick-dots'; - const className = classNames( - prefixCls, - { - [`${prefixCls}-rtl`]: direction === 'rtl', - [`${prefixCls}-vertical`]: newProps.vertical, - }, - hashId, - rootClassName, - ); + const enableDots = !!dots; + const dsClass = classNames( + dotsClass, + `${dotsClass}-${dotPosition}`, + typeof dots === 'boolean' ? false : dots?.className, + ); - return wrapSSR( -
- -
, - ); - }, -); + const [wrapSSR, hashId] = useStyle(prefixCls); + + const className = classNames( + prefixCls, + { + [`${prefixCls}-rtl`]: direction === 'rtl', + [`${prefixCls}-vertical`]: newProps.vertical, + }, + hashId, + rootClassName, + ); + + return wrapSSR( +
+ +
, + ); +}); if (process.env.NODE_ENV !== 'production') { Carousel.displayName = 'Carousel'; diff --git a/components/checkbox/Group.tsx b/components/checkbox/Group.tsx index f62dc19268..4b6a304a65 100644 --- a/components/checkbox/Group.tsx +++ b/components/checkbox/Group.tsx @@ -36,8 +36,11 @@ export interface CheckboxGroupProps extends AbstractCheckboxGroupProps { children?: React.ReactNode; } -const InternalCheckboxGroup: React.ForwardRefRenderFunction = ( - { +const InternalGroup: React.ForwardRefRenderFunction = ( + props, + ref, +) => { + const { defaultValue, children, options = [], @@ -47,9 +50,7 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction { + } = props; const { getPrefixCls, direction } = React.useContext(ConfigContext); const [value, setValue] = React.useState( @@ -63,16 +64,16 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction - options.map((option) => { - if (typeof option === 'string' || typeof option === 'number') { - return { - label: option, - value: option, - }; - } - return option; - }); + const memoOptions = React.useMemo( + () => + options.map((option) => { + if (typeof option === 'string' || typeof option === 'number') { + return { label: option, value: option }; + } + return option; + }), + [options], + ); const cancelValue = (val: string) => { setRegisteredValues((prevValues) => prevValues.filter((v) => v !== val)); @@ -93,13 +94,12 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction registeredValues.includes(val)) .sort((a, b) => { - const indexA = opts.findIndex((opt) => opt.value === a); - const indexB = opts.findIndex((opt) => opt.value === b); + const indexA = memoOptions.findIndex((opt) => opt.value === a); + const indexB = memoOptions.findIndex((opt) => opt.value === b); return indexA - indexB; }), ); @@ -112,23 +112,23 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction 0) { - children = getOptions().map((option) => ( - - {option.label} - - )); - } + const childrenNode = options.length + ? memoOptions.map((option) => ( + + {option.label} + + )) + : children; // eslint-disable-next-line react/jsx-no-constructed-context-values const context = { @@ -151,7 +151,7 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction - {children} + {childrenNode} , ); }; @@ -159,6 +159,6 @@ const InternalCheckboxGroup: React.ForwardRefRenderFunction(InternalCheckboxGroup); +const CheckboxGroup = React.forwardRef(InternalGroup); export default React.memo(CheckboxGroup); diff --git a/components/dropdown/dropdown.tsx b/components/dropdown/dropdown.tsx index eb3e18e80c..ca92efd35b 100644 --- a/components/dropdown/dropdown.tsx +++ b/components/dropdown/dropdown.tsx @@ -318,7 +318,7 @@ function postPureProps(props: DropdownProps) { const PurePanel = genPurePanel(Dropdown, 'dropdown', (prefixCls) => prefixCls, postPureProps); /* istanbul ignore next */ -const WrapPurePanel = (props: DropdownProps) => ( +const WrapPurePanel: React.FC = (props) => ( diff --git a/components/layout/Sider.tsx b/components/layout/Sider.tsx index 4df4f05478..3a015f2b5c 100644 --- a/components/layout/Sider.tsx +++ b/components/layout/Sider.tsx @@ -6,8 +6,8 @@ import omit from 'rc-util/lib/omit'; import * as React from 'react'; import { useContext, useEffect, useRef, useState } from 'react'; -import { ConfigContext } from '../config-provider'; import isNumeric from '../_util/isNumeric'; +import { ConfigContext } from '../config-provider'; import { LayoutContext } from './layout'; const dimensionMaxMap = { @@ -58,172 +58,161 @@ const generateId = (() => { }; })(); -const Sider = React.forwardRef( - ( - { - prefixCls: customizePrefixCls, - className, - trigger, - children, - defaultCollapsed = false, - theme = 'dark', - style = {}, - collapsible = false, - reverseArrow = false, - width = 200, - collapsedWidth = 80, - zeroWidthTriggerStyle, - breakpoint, - onCollapse, - onBreakpoint, - ...props - }, - ref, - ) => { - const { siderHook } = useContext(LayoutContext); +const Sider = React.forwardRef((props, ref) => { + const { + prefixCls: customizePrefixCls, + className, + trigger, + children, + defaultCollapsed = false, + theme = 'dark', + style = {}, + collapsible = false, + reverseArrow = false, + width = 200, + collapsedWidth = 80, + zeroWidthTriggerStyle, + breakpoint, + onCollapse, + onBreakpoint, + ...otherProps + } = props; + const { siderHook } = useContext(LayoutContext); - const [collapsed, setCollapsed] = useState( - 'collapsed' in props ? props.collapsed : defaultCollapsed, - ); - const [below, setBelow] = useState(false); + const [collapsed, setCollapsed] = useState( + 'collapsed' in props ? props.collapsed : defaultCollapsed, + ); + const [below, setBelow] = useState(false); - useEffect(() => { - if ('collapsed' in props) { - setCollapsed(props.collapsed); - } - }, [props.collapsed]); + useEffect(() => { + if ('collapsed' in props) { + setCollapsed(props.collapsed); + } + }, [props.collapsed]); - const handleSetCollapsed = (value: boolean, type: CollapseType) => { - if (!('collapsed' in props)) { - setCollapsed(value); - } - onCollapse?.(value, type); - }; + const handleSetCollapsed = (value: boolean, type: CollapseType) => { + if (!('collapsed' in props)) { + setCollapsed(value); + } + onCollapse?.(value, type); + }; - // ========================= Responsive ========================= - const responsiveHandlerRef = useRef<(mql: MediaQueryListEvent | MediaQueryList) => void>(); - responsiveHandlerRef.current = (mql: MediaQueryListEvent | MediaQueryList) => { - setBelow(mql.matches); - onBreakpoint?.(mql.matches); + // ========================= Responsive ========================= + const responsiveHandlerRef = useRef<(mql: MediaQueryListEvent | MediaQueryList) => void>(); + responsiveHandlerRef.current = (mql: MediaQueryListEvent | MediaQueryList) => { + setBelow(mql.matches); + onBreakpoint?.(mql.matches); - if (collapsed !== mql.matches) { - handleSetCollapsed(mql.matches, 'responsive'); - } - }; + if (collapsed !== mql.matches) { + handleSetCollapsed(mql.matches, 'responsive'); + } + }; - useEffect(() => { - function responsiveHandler(mql: MediaQueryListEvent | MediaQueryList) { - return responsiveHandlerRef.current!(mql); - } + useEffect(() => { + function responsiveHandler(mql: MediaQueryListEvent | MediaQueryList) { + return responsiveHandlerRef.current!(mql); + } - let mql: MediaQueryList; - if (typeof window !== 'undefined') { - const { matchMedia } = window; - if (matchMedia! && breakpoint && breakpoint in dimensionMaxMap) { - mql = matchMedia(`(max-width: ${dimensionMaxMap[breakpoint]})`); - try { - mql.addEventListener('change', responsiveHandler); - } catch (error) { - mql.addListener(responsiveHandler); - } - responsiveHandler(mql); - } - } - return () => { + let mql: MediaQueryList; + if (typeof window !== 'undefined') { + const { matchMedia } = window; + if (matchMedia! && breakpoint && breakpoint in dimensionMaxMap) { + mql = matchMedia(`(max-width: ${dimensionMaxMap[breakpoint]})`); try { - mql?.removeEventListener('change', responsiveHandler); + mql.addEventListener('change', responsiveHandler); } catch (error) { - mql?.removeListener(responsiveHandler); + mql.addListener(responsiveHandler); } - }; - }, [breakpoint]); // in order to accept dynamic 'breakpoint' property, we need to add 'breakpoint' into dependency array. + responsiveHandler(mql); + } + } + return () => { + try { + mql?.removeEventListener('change', responsiveHandler); + } catch (error) { + mql?.removeListener(responsiveHandler); + } + }; + }, [breakpoint]); // in order to accept dynamic 'breakpoint' property, we need to add 'breakpoint' into dependency array. - useEffect(() => { - const uniqueId = generateId('ant-sider-'); - siderHook.addSider(uniqueId); - return () => siderHook.removeSider(uniqueId); - }, []); + useEffect(() => { + const uniqueId = generateId('ant-sider-'); + siderHook.addSider(uniqueId); + return () => siderHook.removeSider(uniqueId); + }, []); - const toggle = () => { - handleSetCollapsed(!collapsed, 'clickTrigger'); + const toggle = () => { + handleSetCollapsed(!collapsed, 'clickTrigger'); + }; + + const { getPrefixCls } = useContext(ConfigContext); + + const renderSider = () => { + const prefixCls = getPrefixCls('layout-sider', customizePrefixCls); + const divProps = omit(otherProps, ['collapsed']); + const rawWidth = collapsed ? collapsedWidth : width; + // use "px" as fallback unit for width + const siderWidth = isNumeric(rawWidth) ? `${rawWidth}px` : String(rawWidth); + // special trigger when collapsedWidth == 0 + const zeroWidthTrigger = + parseFloat(String(collapsedWidth || 0)) === 0 ? ( + + {trigger || } + + ) : null; + const iconObj = { + expanded: reverseArrow ? : , + collapsed: reverseArrow ? : , + }; + const status = collapsed ? 'collapsed' : 'expanded'; + const defaultTrigger = iconObj[status]; + const triggerDom = + trigger !== null + ? zeroWidthTrigger || ( +
+ {trigger || defaultTrigger} +
+ ) + : null; + + const divStyle: React.CSSProperties = { + ...style, + flex: `0 0 ${siderWidth}`, + maxWidth: siderWidth, // Fix width transition bug in IE11 + minWidth: siderWidth, // https://github.com/ant-design/ant-design/issues/6349 + width: siderWidth, }; - const { getPrefixCls } = useContext(ConfigContext); - - const renderSider = () => { - const prefixCls = getPrefixCls('layout-sider', customizePrefixCls); - const divProps = omit(props, ['collapsed']); - const rawWidth = collapsed ? collapsedWidth : width; - // use "px" as fallback unit for width - const siderWidth = isNumeric(rawWidth) ? `${rawWidth}px` : String(rawWidth); - // special trigger when collapsedWidth == 0 - const zeroWidthTrigger = - parseFloat(String(collapsedWidth || 0)) === 0 ? ( - - {trigger || } - - ) : null; - const iconObj = { - expanded: reverseArrow ? : , - collapsed: reverseArrow ? : , - }; - const status = collapsed ? 'collapsed' : 'expanded'; - const defaultTrigger = iconObj[status]; - const triggerDom = - trigger !== null - ? zeroWidthTrigger || ( -
- {trigger || defaultTrigger} -
- ) - : null; - const divStyle = { - ...style, - flex: `0 0 ${siderWidth}`, - maxWidth: siderWidth, // Fix width transition bug in IE11 - minWidth: siderWidth, // https://github.com/ant-design/ant-design/issues/6349 - width: siderWidth, - }; - const siderCls = classNames( - prefixCls, - `${prefixCls}-${theme}`, - { - [`${prefixCls}-collapsed`]: !!collapsed, - [`${prefixCls}-has-trigger`]: collapsible && trigger !== null && !zeroWidthTrigger, - [`${prefixCls}-below`]: !!below, - [`${prefixCls}-zero-width`]: parseFloat(siderWidth) === 0, - }, - className, - ); - return ( - - ); - }; - - const contextValue = React.useMemo( - () => ({ - siderCollapsed: collapsed, - }), - [collapsed], + const siderCls = classNames( + prefixCls, + `${prefixCls}-${theme}`, + { + [`${prefixCls}-collapsed`]: !!collapsed, + [`${prefixCls}-has-trigger`]: collapsible && trigger !== null && !zeroWidthTrigger, + [`${prefixCls}-below`]: !!below, + [`${prefixCls}-zero-width`]: parseFloat(siderWidth) === 0, + }, + className, ); + return ( + + ); + }; - return {renderSider()}; - }, -); + const contextValue = React.useMemo(() => ({ siderCollapsed: collapsed }), [collapsed]); + + return {renderSider()}; +}); if (process.env.NODE_ENV !== 'production') { Sider.displayName = 'Sider'; diff --git a/components/popconfirm/PurePanel.tsx b/components/popconfirm/PurePanel.tsx index a7352e1d3b..6d51fc2163 100644 --- a/components/popconfirm/PurePanel.tsx +++ b/components/popconfirm/PurePanel.tsx @@ -10,7 +10,6 @@ import { ConfigContext } from '../config-provider'; import { useLocale } from '../locale'; import defaultLocale from '../locale/en_US'; import PopoverPurePanel from '../popover/PurePanel'; - import useStyle from './style'; export interface PopconfirmLocale { @@ -100,7 +99,7 @@ export interface PurePanelProps prefixCls?: string; } -export default function PurePanel(props: PurePanelProps) { +const PurePanel: React.FC = (props) => { const { prefixCls: customizePrefixCls, placement, className, style, ...restProps } = props; const { getPrefixCls } = React.useContext(ConfigContext); @@ -115,4 +114,6 @@ export default function PurePanel(props: PurePanelProps) { content={} />, ); -} +}; + +export default PurePanel; diff --git a/components/transfer/ListItem.tsx b/components/transfer/ListItem.tsx index 0bca1a22ff..f74d858395 100644 --- a/components/transfer/ListItem.tsx +++ b/components/transfer/ListItem.tsx @@ -2,10 +2,10 @@ import DeleteOutlined from '@ant-design/icons/DeleteOutlined'; import classNames from 'classnames'; import * as React from 'react'; import type { KeyWiseTransferItem } from '.'; -import Checkbox from '../checkbox'; -import defaultLocale from '../locale/en_US'; -import { useLocale } from '../locale'; import TransButton from '../_util/transButton'; +import Checkbox from '../checkbox'; +import { useLocale } from '../locale'; +import defaultLocale from '../locale/en_US'; type ListItemProps = { renderedText?: string | number; @@ -32,8 +32,7 @@ const ListItem = (props: ListItemProps