diff --git a/.changeset/swift-kids-matter.md b/.changeset/swift-kids-matter.md
new file mode 100644
index 0000000000..f664970f3d
--- /dev/null
+++ b/.changeset/swift-kids-matter.md
@@ -0,0 +1,5 @@
+---
+'@td-design/react-native': minor
+---
+
+对组件库组件进行优化
diff --git a/package.json b/package.json
index c06a538e94..b6eaceda85 100644
--- a/package.json
+++ b/package.json
@@ -59,5 +59,8 @@
"engines": {
"node": ">=16",
"pnpm": ">=7.0.0"
+ },
+ "resolutions": {
+ "@types/react": "17.0.43"
}
-}
+}
\ No newline at end of file
diff --git a/packages/react-native/src/accordion/index.tsx b/packages/react-native/src/accordion/index.tsx
index 3333a625e2..91d8cc3faf 100644
--- a/packages/react-native/src/accordion/index.tsx
+++ b/packages/react-native/src/accordion/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useState } from 'react';
+import React, { FC, useMemo, useState } from 'react';
import { FlatList } from 'react-native';
import Animated from 'react-native-reanimated';
@@ -82,7 +82,7 @@ const AccordionItem: FC<
onPress,
});
- const renderTitle = () => {
+ const Title = useMemo(() => {
if (typeof title === 'string') {
return (
@@ -91,17 +91,18 @@ const AccordionItem: FC<
);
}
return title;
- };
+ }, [title]);
- const renderContent = () => {
- if (typeof content === 'string')
+ const Content = useMemo(() => {
+ if (typeof content === 'string') {
return (
{content}
);
+ }
return content;
- };
+ }, [content]);
return (
@@ -122,7 +123,7 @@ const AccordionItem: FC<
headerStyle,
]}
>
- {renderTitle()}
+ {Title}
{customIcon ? (
customIcon({ progress })
) : (
@@ -133,7 +134,7 @@ const AccordionItem: FC<
- {renderContent()}
+ {Content}
diff --git a/packages/react-native/src/accordion/useAccordion.ts b/packages/react-native/src/accordion/useAccordion.ts
index 08dfc06f19..b55916d219 100644
--- a/packages/react-native/src/accordion/useAccordion.ts
+++ b/packages/react-native/src/accordion/useAccordion.ts
@@ -52,13 +52,8 @@ export default function useAccordion({
}, [multiple, currentIndex, index, onPress]);
const handlePress = () => {
+ progress.value = withTiming(progress.value === 0 ? 1 : 0);
onPress(index);
-
- if (progress.value === 0) {
- progress.value = withTiming(1);
- } else {
- progress.value = withTiming(0);
- }
};
return {
@@ -66,7 +61,7 @@ export default function useAccordion({
iconStyle,
progress,
- handleLayout: useMemoizedFn(handleLayout),
+ handleLayout,
handlePress: useMemoizedFn(handlePress),
};
}
diff --git a/packages/react-native/src/action-sheet/index.tsx b/packages/react-native/src/action-sheet/index.tsx
index a955e75fad..f50c3a3f86 100644
--- a/packages/react-native/src/action-sheet/index.tsx
+++ b/packages/react-native/src/action-sheet/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, ReactNode } from 'react';
+import React, { FC, ReactNode, useMemo } from 'react';
import { StyleSheet } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -52,8 +52,9 @@ const ActionSheet: FC = ({
},
});
- const renderTitle = () => {
+ const Title = useMemo(() => {
if (!title) return null;
+
if (typeof title === 'string')
return (
@@ -62,8 +63,9 @@ const ActionSheet: FC = ({
);
+
return {title};
- };
+ }, [title]);
return (
= ({
maskClosable={false}
maskVisible={true}
>
- {renderTitle()}
+ {Title}
{items.map((item, index) => (
{
- /** 挂件的reader */
- const iconReader = () => {
- if (url) {
- const source = typeof url === 'string' ? { uri: url } : url;
- return (
-
- );
- }
- if (component) {
- return component;
- }
- return null;
- };
- /** 挂件的位置 */
- const styles = StyleSheet.create({
- position: {
- borderRadius: size / 2,
- },
- top: {
- top: 0,
- },
- bottom: {
- bottom: 0,
- },
- left: {
- left: 0,
- },
- right: {
- right: 0,
- },
- });
-
return (
- {iconReader()}
+
);
};
Accessory.displayName = 'Accessory';
+/** 挂件的位置 */
+const styles = StyleSheet.create({
+ top: {
+ top: 0,
+ },
+ bottom: {
+ bottom: 0,
+ },
+ left: {
+ left: 0,
+ },
+ right: {
+ right: 0,
+ },
+});
+
export default Accessory;
+
+const Icon = memo(({ url, size, component }: Pick) => {
+ if (url) {
+ const source = typeof url === 'string' ? { uri: url } : url;
+ return (
+
+ );
+ }
+ if (component) {
+ return component;
+ }
+ return null;
+});
diff --git a/packages/react-native/src/avatar/Avatar/index.tsx b/packages/react-native/src/avatar/Avatar/index.tsx
index 96ab9d5d29..54bd074881 100644
--- a/packages/react-native/src/avatar/Avatar/index.tsx
+++ b/packages/react-native/src/avatar/Avatar/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { Image, StyleSheet } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -27,7 +27,29 @@ const Avatar: FC = ({ title, url, textStyle, ...props }) => {
},
});
- const renderImage = () => {
+ return (
+
+
+
+ );
+};
+Avatar.displayName = 'Avatar';
+
+export default Avatar;
+
+const Content = memo(
+ ({
+ url,
+ title,
+ width,
+ height,
+ avatarRadius,
+ textStyle,
+ }: Pick & {
+ width: number;
+ height: number;
+ avatarRadius: number;
+ }) => {
if (!!url)
return (
= ({ title, url, textStyle, ...props }) => {
);
return null;
- };
-
- return (
-
- {renderImage()}
-
- );
-};
-Avatar.displayName = 'Avatar';
-
-export default Avatar;
+ }
+);
diff --git a/packages/react-native/src/avatar/type.ts b/packages/react-native/src/avatar/type.ts
index 69443a20b8..6c6b9deb46 100644
--- a/packages/react-native/src/avatar/type.ts
+++ b/packages/react-native/src/avatar/type.ts
@@ -1,4 +1,4 @@
-import { PropsWithChildren, ReactNode } from 'react';
+import { PropsWithChildren, ReactElement } from 'react';
import { TextStyle, ViewStyle } from 'react-native';
export interface AccessoryProps {
@@ -7,7 +7,7 @@ export interface AccessoryProps {
/** 使用图片时的值 */
url?: string | number;
/** 使用自定义组件 */
- component?: ReactNode;
+ component?: ReactElement;
/** 挂件垂直方向位置 */
top?: boolean;
/** 挂件水平方向位置 */
diff --git a/packages/react-native/src/badge/index.tsx b/packages/react-native/src/badge/index.tsx
index 7c2999ee88..552cbc686f 100644
--- a/packages/react-native/src/badge/index.tsx
+++ b/packages/react-native/src/badge/index.tsx
@@ -1,9 +1,11 @@
-import React, { cloneElement, FC, ReactElement } from 'react';
-import { TextStyle, ViewStyle } from 'react-native';
+import React, { cloneElement, FC, memo, ReactElement } from 'react';
+import { StyleSheet, TextStyle, ViewStyle } from 'react-native';
import Box from '../box';
+import Text from '../text';
import useBadge from './useBadge';
+const DOT_SIZE = 8; // 默认点大小
export interface BadgeProps {
/** 徽标内容 */
text?: string | number;
@@ -19,18 +21,80 @@ export interface BadgeProps {
children: ReactElement;
}
-const Badge: FC = props => {
- const { renderContent, onBadgeLayout, width, height } = useBadge(props);
+const Badge: FC = ({
+ type = 'text',
+ containerStyle = {},
+ textStyle = {},
+ text,
+ max = 99,
+ children,
+}: BadgeProps) => {
+ const { onBadgeLayout, badgeOffset, layout } = useBadge();
return (
-
- {cloneElement(props.children, {
+
+ {cloneElement(children, {
onLayout: onBadgeLayout,
})}
- {renderContent()}
+
);
};
Badge.displayName = 'Badge';
export default Badge;
+
+const Content = memo(
+ ({
+ type,
+ text,
+ max,
+ containerStyle,
+ textStyle,
+ badgeOffset,
+ }: Pick & {
+ badgeOffset: { top: number; right: number };
+ }) => {
+ text = typeof text === 'number' && text > max! ? `${max}+` : text;
+
+ const isZero = text === '0' || text === 0;
+ const isEmpty = text === null || text === undefined || text === '';
+ const isHidden = isEmpty || isZero;
+
+ if (isHidden) return null;
+
+ if (type === 'dot')
+ return (
+
+ );
+ return (
+
+
+ {text}
+
+
+ );
+ }
+);
diff --git a/packages/react-native/src/badge/useBadge.ts b/packages/react-native/src/badge/useBadge.ts
new file mode 100644
index 0000000000..657e2dbb5f
--- /dev/null
+++ b/packages/react-native/src/badge/useBadge.ts
@@ -0,0 +1,29 @@
+import { LayoutChangeEvent } from 'react-native';
+
+import { useSafeState } from '@td-design/rn-hooks';
+
+export default function useBadge() {
+ const [layout, setLayout] = useSafeState({ width: 0, height: 0 });
+ const [badgeOffset, setBadgeOffset] = useSafeState({
+ top: 0,
+ right: 0,
+ });
+
+ const onBadgeLayout = (event: LayoutChangeEvent) => {
+ const { width, height } = event.nativeEvent.layout;
+ const newX = Math.round(-width / 2);
+ const newY = Math.round(-height / 2);
+
+ setLayout({ width, height });
+
+ if (badgeOffset.top !== newY || badgeOffset.right !== newX) {
+ setBadgeOffset({ top: newY, right: newX });
+ }
+ };
+
+ return {
+ badgeOffset,
+ layout,
+ onBadgeLayout,
+ };
+}
diff --git a/packages/react-native/src/badge/useBadge.tsx b/packages/react-native/src/badge/useBadge.tsx
deleted file mode 100644
index e4b1ff9bab..0000000000
--- a/packages/react-native/src/badge/useBadge.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import React, { useCallback, useState } from 'react';
-import { LayoutChangeEvent, StyleSheet } from 'react-native';
-
-import { useSafeState } from '@td-design/rn-hooks';
-
-import type { BadgeProps } from '.';
-import Box from '../box';
-import Text from '../text';
-
-const DOT_SIZE = 8; // 默认点大小
-export default function useBadge({ type = 'text', containerStyle = {}, textStyle = {}, text, max = 99 }: BadgeProps) {
- text = typeof text === 'number' && text > max ? `${max}+` : text;
-
- const isZero = text === '0' || text === 0;
- const isEmpty = text === null || text === undefined || text === '';
- const isHidden = isEmpty || isZero;
-
- const [layout, setLayout] = useState({ width: 0, height: 0 });
- const [badgeOffset, setBadgeOffset] = useSafeState<{ top: number; right: number }>({
- top: 0,
- right: 0,
- });
-
- const onBadgeLayout = useCallback(
- (event: LayoutChangeEvent) => {
- const { width, height } = event.nativeEvent.layout;
- const newX = Math.round(-width / 2);
- const newY = Math.round(-height / 2);
-
- setLayout({ width, height });
-
- if (badgeOffset.top !== newY || badgeOffset.right !== newX) {
- setBadgeOffset({ top: newY, right: newX });
- }
- },
- [badgeOffset]
- );
-
- const renderContent = () => {
- if (isHidden) return null;
-
- if (type === 'dot')
- return (
-
- );
- return (
-
-
- {text}
-
-
- );
- };
-
- return {
- renderContent,
- onBadgeLayout,
- width: layout.width,
- height: layout.height,
- };
-}
diff --git a/packages/react-native/src/button-group/Item.tsx b/packages/react-native/src/button-group/Item.tsx
index 4932e445e7..7e2efe51a9 100644
--- a/packages/react-native/src/button-group/Item.tsx
+++ b/packages/react-native/src/button-group/Item.tsx
@@ -1,4 +1,4 @@
-import React, { cloneElement, FC, memo, ReactElement, ReactNode } from 'react';
+import React, { cloneElement, FC, memo, ReactElement, ReactNode, useMemo } from 'react';
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -72,7 +72,7 @@ const ButtonItem: FC = ({
},
});
- const renderLabel = () => {
+ const Label = useMemo(() => {
const textColor = isCurrent ? theme.colors.text_active : theme.colors.primary200;
if (typeof label === 'string')
@@ -81,7 +81,7 @@ const ButtonItem: FC = ({
variant={'p1'}
textAlign={'center'}
style={{
- color: disabled ? theme.colors.disabled : textColor,
+ color: disabled ? theme.colors.gray200 : textColor,
}}
>
{label}
@@ -92,7 +92,7 @@ const ButtonItem: FC = ({
color: textColor,
},
});
- };
+ }, [label, isCurrent, disabled, theme.colors.primary200, theme.colors.text_active, theme.colors.gray200]);
if (!disabled)
return (
@@ -104,13 +104,13 @@ const ButtonItem: FC = ({
}}
style={StyleSheet.flatten([styles.item, isFirst && styles.first, isLast && styles.last, itemStyle])}
>
- {renderLabel()}
+ {Label}
);
return (
- {renderLabel()}
+ {Label}
);
};
diff --git a/packages/react-native/src/button/index.tsx b/packages/react-native/src/button/index.tsx
index f553f25d23..b1dbe3399d 100644
--- a/packages/react-native/src/button/index.tsx
+++ b/packages/react-native/src/button/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, ReactNode } from 'react';
+import React, { FC, ReactNode, useMemo } from 'react';
import { DimensionValue } from 'react-native';
import helpers from '../helpers';
@@ -34,7 +34,7 @@ const Button: FC = props => {
const { pressableProps, textColor, variant, indicatorColor } = useButton(props);
- const renderText = () => {
+ const Title = useMemo(() => {
if (typeof title === 'string')
return (
@@ -42,14 +42,14 @@ const Button: FC = props => {
);
return title;
- };
+ }, [title, textColor, variant]);
return (
{!!loading && (
)}
- {renderText()}
+ {Title}
);
};
diff --git a/packages/react-native/src/button/useButton.ts b/packages/react-native/src/button/useButton.ts
index 527103e8ed..c089337cd9 100644
--- a/packages/react-native/src/button/useButton.ts
+++ b/packages/react-native/src/button/useButton.ts
@@ -26,14 +26,14 @@ export default function useButton(props: ButtonProps) {
let textColor: Color = 'text_active';
let backgroundColor = theme.colors.transparent;
- let indicatorColor = disabled ? theme.colors.gray400 : theme.colors.white;
+ let indicatorColor = disabled ? theme.colors.gray200 : theme.colors.white;
if (type === 'primary') {
backgroundColor = disabled ? theme.colors.primary400 : theme.colors.primary200;
} else if (type === 'secondary') {
- textColor = disabled ? 'disabled' : 'primary200';
+ textColor = disabled ? 'gray200' : 'primary200';
backgroundColor = disabled ? theme.colors.disabled : theme.colors.transparent;
- indicatorColor = disabled ? theme.colors.gray400 : theme.colors.primary200;
+ indicatorColor = disabled ? theme.colors.gray200 : theme.colors.primary200;
}
let borderWidth = 0;
diff --git a/packages/react-native/src/card/index.tsx b/packages/react-native/src/card/index.tsx
index d02fc72364..0994268168 100644
--- a/packages/react-native/src/card/index.tsx
+++ b/packages/react-native/src/card/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, PropsWithChildren, ReactNode } from 'react';
+import React, { FC, memo, PropsWithChildren, ReactNode } from 'react';
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -45,9 +45,32 @@ const Card: FC> = ({
contentStyle,
children,
}) => {
- const theme = useTheme();
+ return (
+
+
+ {children}
+ {!!footer && {footer}}
+
+ );
+};
+Card.displayName = 'Card';
- const _renderHeader = () => {
+export default Card;
+
+const Header = memo(
+ ({
+ hideHeader,
+ icon,
+ title,
+ extra,
+ renderHeader,
+ }: Pick) => {
if (hideHeader) return null;
const Header = (
@@ -93,9 +116,13 @@ const Card: FC> = ({
{renderHeader ? renderHeader() : Header}
);
- };
+ }
+);
+
+const Body = memo(
+ ({ footer, contentStyle, children }: Pick, 'footer' | 'contentStyle' | 'children'>) => {
+ const theme = useTheme();
- const _renderBody = () => {
return (
> = ({
{children}
);
- };
-
- const _renderFooter = () => {
- if (!!footer) return {footer};
- return null;
- };
-
- return (
-
- {_renderHeader()}
- {_renderBody()}
- {_renderFooter()}
-
- );
-};
-Card.displayName = 'Card';
-
-export default Card;
+ }
+);
diff --git a/packages/react-native/src/carousel/Bullets.tsx b/packages/react-native/src/carousel/Bullets.tsx
index d955d316a6..7e53b52021 100644
--- a/packages/react-native/src/carousel/Bullets.tsx
+++ b/packages/react-native/src/carousel/Bullets.tsx
@@ -58,25 +58,27 @@ const Bullets = ({
};
Bullets.displayName = 'Bullets';
-const Dot = (props: { isCurrent: boolean; activeColor?: string; inactiveColor?: string; indicatorSize: number }) => {
- const theme = useTheme();
- const { isCurrent, activeColor = theme.colors.gray50, inactiveColor = theme.colors.gray200, indicatorSize } = props;
+export default memo(Bullets);
- const backgroundColor = mixColor(+isCurrent, inactiveColor, activeColor) as any;
- const scale = mix(+isCurrent, 1, 1.2);
+const Dot = memo(
+ (props: { isCurrent: boolean; activeColor?: string; inactiveColor?: string; indicatorSize: number }) => {
+ const theme = useTheme();
+ const { isCurrent, activeColor = theme.colors.gray50, inactiveColor = theme.colors.gray200, indicatorSize } = props;
- const styles = StyleSheet.create({
- dot: {
- width: indicatorSize,
- height: indicatorSize,
- borderRadius: indicatorSize / 2,
- backgroundColor,
- transform: [{ scale }],
- marginHorizontal: indicatorSize / 2,
- },
- });
+ const backgroundColor = mixColor(+isCurrent, inactiveColor, activeColor) as any;
+ const scale = mix(+isCurrent, 1, 1.2);
- return ;
-};
+ const styles = StyleSheet.create({
+ dot: {
+ width: indicatorSize,
+ height: indicatorSize,
+ borderRadius: indicatorSize / 2,
+ backgroundColor,
+ transform: [{ scale }],
+ marginHorizontal: indicatorSize / 2,
+ },
+ });
-export default memo(Bullets);
+ return ;
+ }
+);
diff --git a/packages/react-native/src/carousel/useCarousel.ts b/packages/react-native/src/carousel/useCarousel.ts
index fd1834a46f..8d3843af54 100644
--- a/packages/react-native/src/carousel/useCarousel.ts
+++ b/packages/react-native/src/carousel/useCarousel.ts
@@ -21,6 +21,12 @@ export default function useCarousel({
setCurrentIndex(index => (index === count - 1 ? 0 : index + 1));
});
+ // 用户手动滚动开始时,停止轮播
+ const clearTimer = useMemoizedFn(() => {
+ clearInterval(timer.current);
+ timer.current = undefined;
+ });
+
useEffect(() => {
if (!auto) return;
@@ -37,12 +43,6 @@ export default function useCarousel({
timer.current = setInterval(loop, duration);
};
- // 用户手动滚动开始时,停止轮播
- const clearTimer = () => {
- clearInterval(timer.current);
- timer.current = undefined;
- };
-
// 在ScrollView滚动结束后,修改当前index
const onScrollEnd = (e: NativeSyntheticEvent) => {
const { x } = e.nativeEvent.contentOffset;
@@ -64,7 +64,7 @@ export default function useCarousel({
scrollViewRef,
currentIndex,
- onTouchStart: useMemoizedFn(clearTimer),
+ onTouchStart: clearTimer,
onTouchEnd: useMemoizedFn(onTouchEnd),
onScrollEnd: useMemoizedFn(onScrollEnd),
};
diff --git a/packages/react-native/src/checkbox/CheckboxItem.tsx b/packages/react-native/src/checkbox/CheckboxItem.tsx
index 655186c788..f4f1eab041 100644
--- a/packages/react-native/src/checkbox/CheckboxItem.tsx
+++ b/packages/react-native/src/checkbox/CheckboxItem.tsx
@@ -1,7 +1,8 @@
-import React, { FC, memo } from 'react';
+import React, { FC, memo, useMemo } from 'react';
import { Keyboard, StyleSheet } from 'react-native';
import { useTheme } from '@shopify/restyle';
+import { useMemoizedFn } from '@td-design/rn-hooks';
import Box from '../box';
import Flex from '../flex';
@@ -38,13 +39,13 @@ const CheckboxItem: FC = ({
},
});
- const handleChange = () => {
+ const handleChange = useMemoizedFn(() => {
Keyboard.dismiss();
if (disabled) return;
onChange?.(value, status);
- };
+ });
- const renderLabel = () => {
+ const Label = useMemo(() => {
if (typeof label === 'string')
return (
@@ -52,7 +53,7 @@ const CheckboxItem: FC = ({
);
return label;
- };
+ }, [disabled, label, labelStyle]);
if (!disabled)
return (
@@ -65,7 +66,7 @@ const CheckboxItem: FC = ({
- {renderLabel()}
+ {Label}
);
@@ -76,7 +77,7 @@ const CheckboxItem: FC = ({
- {renderLabel()}
+ {Label}
);
diff --git a/packages/react-native/src/collapse-text/index.tsx b/packages/react-native/src/collapse-text/index.tsx
index aaf98fb182..e08db07d74 100644
--- a/packages/react-native/src/collapse-text/index.tsx
+++ b/packages/react-native/src/collapse-text/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useCallback } from 'react';
+import React, { FC } from 'react';
import { LayoutChangeEvent, StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native';
import { useBoolean } from '@td-design/rn-hooks';
@@ -45,17 +45,14 @@ const CollapseText: FC = ({
const [isOverflow, { set: setOverflow }] = useBoolean(false);
const [hidden, { toggle: toggleHidden }] = useBoolean(true);
- const handleLayout = useCallback(
- (e: LayoutChangeEvent) => {
- const { height } = e.nativeEvent.layout;
- if (height - 1 < lineHeight * defaultNumberOfLines) {
- setOverflow(false);
- } else {
- setOverflow(true);
- }
- },
- [lineHeight, defaultNumberOfLines]
- );
+ const handleLayout = (e: LayoutChangeEvent) => {
+ const { height } = e.nativeEvent.layout;
+ if (height - 1 < lineHeight * defaultNumberOfLines) {
+ setOverflow(false);
+ } else {
+ setOverflow(true);
+ }
+ };
const styles = StyleSheet.create({
container: {
diff --git a/packages/react-native/src/count-down/index.tsx b/packages/react-native/src/count-down/index.tsx
index d61a6ed42a..eb2166aff6 100644
--- a/packages/react-native/src/count-down/index.tsx
+++ b/packages/react-native/src/count-down/index.tsx
@@ -104,7 +104,7 @@ const CountDown = forwardRef(
activeOpacity={activeOpacity}
onPress={handlePress}
>
-
+
{text}
diff --git a/packages/react-native/src/empty/index.tsx b/packages/react-native/src/empty/index.tsx
index cdb26f6aca..8e0e92766a 100644
--- a/packages/react-native/src/empty/index.tsx
+++ b/packages/react-native/src/empty/index.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode } from 'react';
+import React, { ReactNode, useMemo } from 'react';
import Svg, { Ellipse, G, Path } from 'react-native-svg';
import { BoxProps } from '@shopify/restyle';
@@ -15,7 +15,7 @@ type EmptyProps = BoxProps & {
};
const Empty: React.FC = ({ emptyText = '暂无数据', customImg, ...boxProps }) => {
- const renderTextDom = () => {
+ const EmptyText = useMemo(() => {
if (typeof emptyText === 'string') {
return (
@@ -24,9 +24,9 @@ const Empty: React.FC = ({ emptyText = '暂无数据', customImg, ..
);
}
return emptyText;
- };
+ }, [emptyText]);
- const renderImgDom = () => {
+ const EmptyImage = useMemo(() => {
if (customImg) return customImg;
return (
@@ -43,12 +43,12 @@ const Empty: React.FC = ({ emptyText = '暂无数据', customImg, ..
);
- };
+ }, [customImg]);
return (
- {renderImgDom()}
- {renderTextDom()}
+ {EmptyImage}
+ {EmptyText}
);
};
diff --git a/packages/react-native/src/float-button/Actions.tsx b/packages/react-native/src/float-button/Actions.tsx
index efee327c5e..f1ff2bc15a 100644
--- a/packages/react-native/src/float-button/Actions.tsx
+++ b/packages/react-native/src/float-button/Actions.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { StyleSheet } from 'react-native';
import Box from '../box';
@@ -33,4 +33,4 @@ const Actions: FC = props => {
};
Actions.displayName = 'Actions';
-export default Actions;
+export default memo(Actions);
diff --git a/packages/react-native/src/flow/index.tsx b/packages/react-native/src/flow/index.tsx
index 328c5b4c97..f27fd1b744 100644
--- a/packages/react-native/src/flow/index.tsx
+++ b/packages/react-native/src/flow/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useCallback } from 'react';
+import React, { FC } from 'react';
import { LayoutChangeEvent } from 'react-native';
import { useSafeState } from '@td-design/rn-hooks';
@@ -33,9 +33,9 @@ const Flow: FC = ({ steps = [], size = px(36), current = 0, status =
/** 单条线的长度 */
const tailWidth = (wrapWidth - iconWidth) / (steps.length - 1);
- const handleLayout = useCallback((e: LayoutChangeEvent) => {
+ const handleLayout = (e: LayoutChangeEvent) => {
setWrapWidth(e.nativeEvent.layout.width);
- }, []);
+ };
return (
diff --git a/packages/react-native/src/flow/step.tsx b/packages/react-native/src/flow/step.tsx
index 3874182687..901880d39f 100644
--- a/packages/react-native/src/flow/step.tsx
+++ b/packages/react-native/src/flow/step.tsx
@@ -1,4 +1,4 @@
-import React, { cloneElement, FC, isValidElement, memo, ReactElement } from 'react';
+import React, { cloneElement, FC, isValidElement, memo, ReactElement, useMemo } from 'react';
import { useTheme } from '@shopify/restyle';
@@ -72,7 +72,7 @@ const Step: FC = ({
* 3 更具当前的状态进行选择使用的icon
* 4 可以使用label
*/
- const iconRender = () => {
+ const IconRender = useMemo(() => {
if (!!stepRender && isValidElement(stepRender)) {
return cloneElement(stepRender as ReactElement, {});
}
@@ -91,12 +91,12 @@ const Step: FC = ({
);
}
return ;
- };
+ }, [icon, iconSize, label, stepRender, status, theme.colors.white]);
/**
* 尾巴的样式
*/
- const tailRender = () => {
+ const TailRender = useMemo(() => {
if (isLast) return null;
if (!active || isCurrent)
return (
@@ -113,14 +113,14 @@ const Step: FC = ({
}}
/>
);
- };
+ }, [active, iconActiveColor, isCurrent, isLast, size]);
return (
{stepRender ? (
- iconRender()
+ IconRender
) : (
= ({
borderRadius: size / 2,
}}
>
- {iconRender()}
+ {IconRender}
)}
@@ -151,7 +151,7 @@ const Step: FC = ({
)}
- {tailRender()}
+ {TailRender}
);
};
diff --git a/packages/react-native/src/form/FormItem.tsx b/packages/react-native/src/form/FormItem.tsx
index 1a80850e84..58121d945b 100644
--- a/packages/react-native/src/form/FormItem.tsx
+++ b/packages/react-native/src/form/FormItem.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useContext, useRef } from 'react';
+import React, { FC, useContext, useMemo, useRef } from 'react';
import { useTheme } from '@shopify/restyle';
import { useSafeState } from '@td-design/rn-hooks';
@@ -37,12 +37,15 @@ const FormItem: FC = ({ children, type = 'bottom', name, ...field
return {};
};
- const Error =
- errors.length > 0 ? (
+ const Error = useMemo(() => {
+ if (errors.length === 0) return null;
+
+ return (
{errors[0]}
- ) : null;
+ );
+ }, [errors]);
return (
diff --git a/packages/react-native/src/form/FormListItem.tsx b/packages/react-native/src/form/FormListItem.tsx
index 90dd68dc63..ee9b8cba4d 100644
--- a/packages/react-native/src/form/FormListItem.tsx
+++ b/packages/react-native/src/form/FormListItem.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useContext, useRef } from 'react';
+import React, { FC, useContext, useMemo, useRef } from 'react';
import { useTheme } from '@shopify/restyle';
import { useSafeState } from '@td-design/rn-hooks';
@@ -39,12 +39,15 @@ const FormListItem: FC = ({
}
};
- const Error =
- errors.length > 0 ? (
+ const Error = useMemo(() => {
+ if (errors.length === 0) return null;
+
+ return (
{errors[0]}
- ) : null;
+ );
+ }, [errors]);
return (
= props => {
},
});
- const renderHeaderLeft = () => {
+ const HeaderLeft = useMemo(() => {
if (headerLeft) {
if (typeof headerLeft === 'string') {
return (
@@ -77,14 +77,14 @@ const ImageHeader: FC = props => {
return headerLeft;
}
return ;
- };
+ }, [headerLeft, headerLeftColor]);
return (
{showLeft ? (
- {renderHeaderLeft()}
+ {HeaderLeft}
) : (
diff --git a/packages/react-native/src/input/InputItem.tsx b/packages/react-native/src/input/InputItem.tsx
index 8d7f5fb363..053e8aeb44 100644
--- a/packages/react-native/src/input/InputItem.tsx
+++ b/packages/react-native/src/input/InputItem.tsx
@@ -1,4 +1,4 @@
-import React, { forwardRef, ReactNode } from 'react';
+import React, { forwardRef, memo, ReactNode } from 'react';
import { StyleProp, StyleSheet, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';
import Animated, { FadeInRight, FadeOutRight } from 'react-native-reanimated';
@@ -67,15 +67,12 @@ const InputItem = forwardRef(
ref
) => {
const theme = useTheme();
- const { LabelComp, inputValue, eyeOpen, handleChange, handleInputClear, triggerPasswordType } = useInputItem({
+ const { inputValue, eyeOpen, handleChange, handleInputClear, triggerPasswordType } = useInputItem({
inputType,
- label,
value,
defaultValue,
onChange,
onClear,
- colon,
- required,
});
const styles = StyleSheet.create({
@@ -140,7 +137,7 @@ const InputItem = forwardRef(
return (
- {LabelComp}
+
{InputContent}
{!!extra && (
@@ -172,3 +169,26 @@ const InputItem = forwardRef(
InputItem.displayName = 'InputItem';
export default InputItem;
+
+const Label = memo(({ colon, label, required }: Pick) => {
+ if (!label) return null;
+
+ if (typeof label === 'string')
+ return (
+
+ {required && *}
+
+ {label}
+
+ {!!colon && :}
+
+ );
+
+ return (
+
+ {required && *}
+ {label}
+ {!!colon && :}
+
+ );
+});
diff --git a/packages/react-native/src/input/TextArea.tsx b/packages/react-native/src/input/TextArea.tsx
index afc247cef4..058345d54a 100644
--- a/packages/react-native/src/input/TextArea.tsx
+++ b/packages/react-native/src/input/TextArea.tsx
@@ -1,4 +1,4 @@
-import React, { forwardRef, ReactNode } from 'react';
+import React, { forwardRef, memo, ReactNode } from 'react';
import { StyleProp, StyleSheet, TextInput, TextInputProps, ViewStyle } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -39,7 +39,7 @@ const TextArea = forwardRef(
ref
) => {
const theme = useTheme();
- const { inputValue, handleChange, LabelComp } = useTextArea({ value, onChange, required, label });
+ const { inputValue, handleChange } = useTextArea({ value, onChange });
const styles = StyleSheet.create({
input: {
@@ -53,7 +53,7 @@ const TextArea = forwardRef(
return (
- {LabelComp}
+
(
TextArea.displayName = 'TextArea';
export default TextArea;
+
+const Label = memo(({ label, required }: Pick) => {
+ if (!label) return null;
+
+ if (typeof label === 'string')
+ return (
+
+ {required && *}
+
+ {label}
+
+
+ );
+
+ return (
+
+ {required && *}
+ {label}
+
+ );
+});
diff --git a/packages/react-native/src/input/index.tsx b/packages/react-native/src/input/index.tsx
index aea4cdd9df..1b92586340 100644
--- a/packages/react-native/src/input/index.tsx
+++ b/packages/react-native/src/input/index.tsx
@@ -1,4 +1,4 @@
-import React, { forwardRef, ReactNode } from 'react';
+import React, { forwardRef, memo, ReactNode } from 'react';
import { StyleProp, StyleSheet, TextInput, TextInputProps, TextStyle } from 'react-native';
import Animated, { FadeInRight, FadeOutRight } from 'react-native-reanimated';
@@ -62,8 +62,8 @@ const Input = forwardRef(
value,
onChange,
onClear,
- colon,
- required,
+ colon = false,
+ required = false,
style,
brief,
defaultValue,
@@ -72,16 +72,12 @@ const Input = forwardRef(
ref
) => {
const theme = useTheme();
- const { LabelComp, inputValue, eyeOpen, handleChange, handleInputClear, triggerPasswordType } = useInput({
- labelPosition,
+ const { inputValue, eyeOpen, handleChange, handleInputClear, triggerPasswordType } = useInput({
inputType,
- label,
value,
defaultValue,
onChange,
onClear,
- colon,
- required,
});
const styles = StyleSheet.create({
@@ -147,31 +143,19 @@ const Input = forwardRef(
);
- const Brief = brief ? (
-
- {typeof brief === 'string' ? (
-
- {brief}
-
- ) : (
- brief
- )}
-
- ) : null;
-
return labelPosition === 'left' ? (
- {LabelComp}
+
{InputContent}
- {Brief}
+
) : (
- {LabelComp}
+
{InputContent}
- {Brief}
+
);
}
@@ -182,3 +166,41 @@ export default Object.assign(Input, {
InputItem,
TextArea,
});
+
+const Label = memo(({ colon, label, required }: Pick) => {
+ if (!label) return null;
+
+ if (typeof label === 'string')
+ return (
+
+ {required && *}
+
+
+
+ {colon ? ':' : ''}
+
+ );
+
+ return (
+
+ {required && *}
+
+ {colon ? ':' : ''}
+
+ );
+});
+
+const Brief = memo(({ brief }: Pick) => {
+ if (!brief) return null;
+ return (
+
+ {typeof brief === 'string' ? (
+
+ {brief}
+
+ ) : (
+ brief
+ )}
+
+ );
+});
diff --git a/packages/react-native/src/input/useInput.ts b/packages/react-native/src/input/useInput.ts
new file mode 100644
index 0000000000..95395afb14
--- /dev/null
+++ b/packages/react-native/src/input/useInput.ts
@@ -0,0 +1,43 @@
+import { useEffect } from 'react';
+
+import { useMemoizedFn, useSafeState } from '@td-design/rn-hooks';
+
+import type { InputProps } from '.';
+
+export default function useInput({
+ inputType,
+ value,
+ defaultValue,
+ onChange,
+ onClear,
+}: Pick) {
+ const [inputValue, setInputValue] = useSafeState();
+ const [eyeOpen, setEyeOpen] = useSafeState(inputType === 'password');
+
+ useEffect(() => {
+ setInputValue(value || defaultValue);
+ }, [value, defaultValue]);
+
+ const handleInputClear = () => {
+ setInputValue('');
+ onChange?.('');
+ onClear?.();
+ };
+
+ const handleChange = (val: string) => {
+ setInputValue(val);
+ onChange?.(val);
+ };
+
+ const triggerPasswordType = () => {
+ setEyeOpen(!eyeOpen);
+ };
+
+ return {
+ inputValue,
+ eyeOpen,
+ handleChange: useMemoizedFn(handleChange),
+ handleInputClear: useMemoizedFn(handleInputClear),
+ triggerPasswordType: useMemoizedFn(triggerPasswordType),
+ };
+}
diff --git a/packages/react-native/src/input/useInput.tsx b/packages/react-native/src/input/useInput.tsx
deleted file mode 100644
index 1bbc0d58f3..0000000000
--- a/packages/react-native/src/input/useInput.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import React, { useEffect, useMemo } from 'react';
-
-import { useMemoizedFn, useSafeState } from '@td-design/rn-hooks';
-
-import type { InputProps } from '.';
-import Flex from '../flex';
-import Text from '../text';
-
-export default function useInput({
- inputType,
- labelPosition,
- label,
- value,
- defaultValue,
- onChange,
- onClear,
- colon = false,
- required = false,
-}: Pick<
- InputProps,
- 'inputType' | 'labelPosition' | 'label' | 'value' | 'defaultValue' | 'onChange' | 'onClear' | 'colon' | 'required'
->) {
- const [inputValue, setInputValue] = useSafeState();
- const [eyeOpen, setEyeOpen] = useSafeState(inputType === 'password');
-
- useEffect(() => {
- setInputValue(value || defaultValue);
- }, [value, defaultValue]);
-
- const handleInputClear = () => {
- setInputValue('');
- onChange?.('');
- onClear?.();
- };
-
- const handleChange = (val: string) => {
- setInputValue(val);
- onChange?.(val);
- };
-
- const triggerPasswordType = () => {
- setEyeOpen(!eyeOpen);
- };
-
- const LabelComp = useMemo(() => {
- if (label) {
- if (typeof label === 'string') {
- return (
-
- {required && *}
-
- {label}
-
- {colon ? ':' : ''}
-
- );
- }
- return (
-
- {required && *}
- {label}
- {colon ? ':' : ''}
-
- );
- }
- return null;
- }, [colon, label, labelPosition, required]);
-
- return {
- LabelComp,
- inputValue,
- eyeOpen,
- handleChange: useMemoizedFn(handleChange),
- handleInputClear: useMemoizedFn(handleInputClear),
- triggerPasswordType: useMemoizedFn(triggerPasswordType),
- };
-}
diff --git a/packages/react-native/src/input/useInputItem.ts b/packages/react-native/src/input/useInputItem.ts
new file mode 100644
index 0000000000..b3dfdf9113
--- /dev/null
+++ b/packages/react-native/src/input/useInputItem.ts
@@ -0,0 +1,43 @@
+import { useEffect } from 'react';
+
+import { useMemoizedFn, useSafeState } from '@td-design/rn-hooks';
+
+import type { InputItemProps } from './InputItem';
+
+export default function useInputItem({
+ inputType,
+ value,
+ defaultValue,
+ onChange,
+ onClear,
+}: Pick) {
+ const [inputValue, setInputValue] = useSafeState();
+ const [eyeOpen, setEyeOpen] = useSafeState(inputType === 'password');
+
+ useEffect(() => {
+ setInputValue(value || defaultValue);
+ }, [value, defaultValue]);
+
+ const handleInputClear = () => {
+ setInputValue('');
+ onChange?.('');
+ onClear?.();
+ };
+
+ const handleChange = (val: string) => {
+ setInputValue(val);
+ onChange?.(val);
+ };
+
+ const triggerPasswordType = () => {
+ setEyeOpen(!eyeOpen);
+ };
+
+ return {
+ inputValue,
+ eyeOpen,
+ handleChange: useMemoizedFn(handleChange),
+ handleInputClear: useMemoizedFn(handleInputClear),
+ triggerPasswordType: useMemoizedFn(triggerPasswordType),
+ };
+}
diff --git a/packages/react-native/src/input/useInputItem.tsx b/packages/react-native/src/input/useInputItem.tsx
deleted file mode 100644
index 1661879983..0000000000
--- a/packages/react-native/src/input/useInputItem.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React, { useEffect, useMemo } from 'react';
-
-import { useMemoizedFn, useSafeState } from '@td-design/rn-hooks';
-
-import Flex from '../flex';
-import Text from '../text';
-import type { InputItemProps } from './InputItem';
-
-export default function useInputItem({
- inputType,
- label,
- value,
- defaultValue,
- onChange,
- onClear,
- colon = false,
- required = false,
-}: Pick<
- InputItemProps,
- 'inputType' | 'label' | 'value' | 'defaultValue' | 'onChange' | 'onClear' | 'colon' | 'required'
->) {
- const [inputValue, setInputValue] = useSafeState();
- const [eyeOpen, setEyeOpen] = useSafeState(inputType === 'password');
-
- useEffect(() => {
- setInputValue(value || defaultValue);
- }, [value, defaultValue]);
-
- const handleInputClear = () => {
- setInputValue('');
- onChange?.('');
- onClear?.();
- };
-
- const handleChange = (val: string) => {
- setInputValue(val);
- onChange?.(val);
- };
-
- const triggerPasswordType = () => {
- setEyeOpen(!eyeOpen);
- };
-
- const LabelComp = useMemo(() => {
- if (label) {
- if (typeof label === 'string') {
- return (
-
- {required && *}
-
- {label}
-
- {!!colon && :}
-
- );
- }
- return (
-
- {required && *}
- {label}
- {!!colon && :}
-
- );
- }
- return null;
- }, [colon, label, required]);
-
- return {
- LabelComp,
- inputValue,
- eyeOpen,
- handleChange: useMemoizedFn(handleChange),
- handleInputClear: useMemoizedFn(handleInputClear),
- triggerPasswordType: useMemoizedFn(triggerPasswordType),
- };
-}
diff --git a/packages/react-native/src/input/useTextArea.ts b/packages/react-native/src/input/useTextArea.ts
new file mode 100644
index 0000000000..305664a17b
--- /dev/null
+++ b/packages/react-native/src/input/useTextArea.ts
@@ -0,0 +1,23 @@
+import { useEffect } from 'react';
+
+import { useSafeState } from '@td-design/rn-hooks';
+
+import type { TextAreaProps } from './TextArea';
+
+export default function useTextArea({ value = '', onChange }: Pick) {
+ const [inputValue, setInputValue] = useSafeState(value);
+
+ useEffect(() => {
+ setInputValue(value);
+ }, [value]);
+
+ const handleChange = (val: string) => {
+ setInputValue(val);
+ onChange?.(val);
+ };
+
+ return {
+ inputValue,
+ handleChange,
+ };
+}
diff --git a/packages/react-native/src/input/useTextArea.tsx b/packages/react-native/src/input/useTextArea.tsx
deleted file mode 100644
index 7c11660b99..0000000000
--- a/packages/react-native/src/input/useTextArea.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import React, { useEffect, useMemo } from 'react';
-
-import { useSafeState } from '@td-design/rn-hooks';
-
-import Flex from '../flex';
-import Text from '../text';
-import type { TextAreaProps } from './TextArea';
-
-export default function useTextArea({
- value = '',
- onChange,
- label,
- required = false,
-}: Pick) {
- const [inputValue, setInputValue] = useSafeState(value);
-
- useEffect(() => {
- setInputValue(value);
- }, [value]);
-
- const handleChange = (val: string) => {
- setInputValue(val);
- onChange?.(val);
- };
-
- const LabelComp = useMemo(() => {
- if (label) {
- if (typeof label === 'string') {
- return (
-
- {required && *}
-
- {label}
-
-
- );
- }
- return (
-
- {required && *}
- {label}
-
- );
- }
- return null;
- }, [label, required]);
-
- return {
- inputValue,
- handleChange,
- LabelComp,
- };
-}
diff --git a/packages/react-native/src/list-item/index.tsx b/packages/react-native/src/list-item/index.tsx
index 1158975548..b65b651192 100644
--- a/packages/react-native/src/list-item/index.tsx
+++ b/packages/react-native/src/list-item/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, memo, PropsWithChildren, ReactElement, ReactNode } from 'react';
+import React, { FC, memo, PropsWithChildren, ReactElement, ReactNode, useMemo } from 'react';
import { Keyboard, StyleProp, ViewStyle } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -44,9 +44,7 @@ export type ListItemProps = {
backgroundColor?: string;
};
-type BriefBasePropsType = PropsWithChildren>;
-
-const Brief: FC = props => {
+const Brief: FC>> = props => {
const { children, wrap } = props;
const numberOfLines = wrap ? {} : { numberOfLines: 1 };
return (
@@ -75,21 +73,58 @@ const ListItem = ({
required = false,
activeOpacity = 0.6,
}: ListItemProps) => {
+ if (!onPress)
+ return (
+
+
+
+ );
+
+ return (
+ {
+ Keyboard.dismiss();
+ onPress();
+ }}
+ >
+
+
+ );
+};
+ListItem.displayName = 'ListItem';
+
+export default memo(ListItem);
+
+const Content = ({
+ backgroundColor,
+ style,
+ required,
+ thumb,
+ title,
+ brief,
+ wrap,
+ extra,
+ arrow,
+}: Omit) => {
const theme = useTheme();
- const renderTitle = () => (
-
- {typeof title === 'string' ? (
-
- {title}
-
- ) : (
- title
- )}
-
+ const Title = useMemo(
+ () => (
+
+ {typeof title === 'string' ? (
+
+ {title}
+
+ ) : (
+ title
+ )}
+
+ ),
+ [thumb, title]
);
- const renderExtra = () => {
+ const Extra = useMemo(() => {
if (!extra) return null;
if (typeof extra === 'string') {
const numberOfLines = wrap ? {} : { numberOfLines: 1 };
@@ -108,9 +143,9 @@ const ListItem = ({
);
}
return extra;
- };
+ }, [extra, wrap]);
- const renderArrow = () => {
+ const Arrow = useMemo(() => {
if (!arrow) return null;
if (typeof arrow === 'string')
return (
@@ -119,9 +154,9 @@ const ListItem = ({
);
return arrow;
- };
+ }, [arrow, theme.colors.icon]);
- const renderContent = () => (
+ return (
)}
{thumb}
- {renderTitle()}
+ {Title}
- {renderExtra()}
+ {Extra}
{!!brief && {brief}}
- {renderArrow()}
+ {Arrow}
);
-
- if (!onPress) return {renderContent()};
-
- return (
- {
- Keyboard.dismiss();
- onPress();
- }}
- >
- {renderContent()}
-
- );
};
-ListItem.displayName = 'ListItem';
-
-export default memo(ListItem);
diff --git a/packages/react-native/src/list/index.tsx b/packages/react-native/src/list/index.tsx
index 96c9dcfdbe..cdf5745a48 100644
--- a/packages/react-native/src/list/index.tsx
+++ b/packages/react-native/src/list/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, ReactNode } from 'react';
+import React, { FC, memo, ReactNode, useMemo } from 'react';
import { StyleProp, TextStyle, ViewStyle } from 'react-native';
import Box from '../box';
@@ -20,17 +20,17 @@ type ListProps = {
itemBackgroundColor?: string;
};
const List: FC = ({ header, extra, itemBackgroundColor, items = [] }) => {
- const renderHeader = () => {
+ const Header = useMemo(() => {
if (!header) return null;
if (typeof header === 'string') {
return ;
}
return header;
- };
+ }, [header, extra]);
return (
- {renderHeader()}
+ {Header}
{items.map((props, index) => {
return ;
})}
@@ -39,42 +39,44 @@ const List: FC = ({ header, extra, itemBackgroundColor, items = [] })
};
List.displayName = 'List';
-const ListHeader = ({
- text,
- extra,
- textStyle,
- headerStyle,
-}: {
- /** 标题文本 */
- text: string;
- /** 自定义右侧内容 */
- extra?: ReactNode;
- /** 文本样式 */
- textStyle?: StyleProp;
- /** 标题样式 */
- headerStyle?: StyleProp;
-}) => {
- if (text === '') return null;
- return (
-
-
-
- {text}
-
-
- {extra}
-
- );
-};
+const ListHeader = memo(
+ ({
+ text,
+ extra,
+ textStyle,
+ headerStyle,
+ }: {
+ /** 标题文本 */
+ text: string;
+ /** 自定义右侧内容 */
+ extra?: ReactNode;
+ /** 文本样式 */
+ textStyle?: StyleProp;
+ /** 标题样式 */
+ headerStyle?: StyleProp;
+ }) => {
+ if (text === '') return null;
+ return (
+
+
+
+ {text}
+
+
+ {extra}
+
+ );
+ }
+);
ListHeader.displayName = 'ListHeader';
export default Object.assign(List, { ListHeader });
diff --git a/packages/react-native/src/menu/Chevron.tsx b/packages/react-native/src/menu/Chevron.tsx
index fe3ef6270a..b6c65e3d39 100644
--- a/packages/react-native/src/menu/Chevron.tsx
+++ b/packages/react-native/src/menu/Chevron.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
import { mix } from 'react-native-redash';
@@ -20,4 +20,4 @@ const Chevron: FC<{ progress: Animated.SharedValue }> = ({ progress }) =
);
};
-export default Chevron;
+export default memo(Chevron);
diff --git a/packages/react-native/src/menu/MenuGroup.tsx b/packages/react-native/src/menu/MenuGroup.tsx
index 463a5bb1b8..c91e8446e9 100644
--- a/packages/react-native/src/menu/MenuGroup.tsx
+++ b/packages/react-native/src/menu/MenuGroup.tsx
@@ -1,4 +1,4 @@
-import React, { PropsWithChildren } from 'react';
+import React, { memo, PropsWithChildren } from 'react';
import Animated from 'react-native-reanimated';
import { useTheme } from '@shopify/restyle';
@@ -67,4 +67,4 @@ const MenuGroup = ({
};
MenuGroup.displayName = 'MenuGroup';
-export default MenuGroup;
+export default memo(MenuGroup);
diff --git a/packages/react-native/src/menu/useGroup.ts b/packages/react-native/src/menu/useGroup.ts
index 9bfce5b7c6..1d91ff9078 100644
--- a/packages/react-native/src/menu/useGroup.ts
+++ b/packages/react-native/src/menu/useGroup.ts
@@ -49,7 +49,7 @@ export default function useGroup({
bodyStyle,
progress,
- handleLayout: useMemoizedFn(handleLayout),
+ handleLayout,
handlePress: useMemoizedFn(handlePress),
};
}
diff --git a/packages/react-native/src/notice-bar/AnimatedNotice.tsx b/packages/react-native/src/notice-bar/AnimatedNotice.tsx
index 8e24a53b10..9e96f5dc96 100644
--- a/packages/react-native/src/notice-bar/AnimatedNotice.tsx
+++ b/packages/react-native/src/notice-bar/AnimatedNotice.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useEffect, useState } from 'react';
+import React, { FC, memo, useEffect, useState } from 'react';
import { LayoutChangeEvent } from 'react-native';
import Animated, {
Easing,
@@ -94,4 +94,4 @@ const AnimatedNotice: FC = props => {
const [visible, setVisible] = useState(true);
const [height, setHeight] = useState(0);
- const onContentLayout = useMemoizedFn(e => {
+ const handleContentLayout = (e: LayoutChangeEvent) => {
setHeight(e.nativeEvent.layout.height);
- });
+ };
if (!visible) return null;
- const BaseContent = ;
-
- const WrapComp = ({ children }: PropsWithChildren<{}>) => {
- if (onPress)
- return (
-
- {children}
-
- );
- return <>{children}>;
- };
+ const BaseContent = (
+
+ );
switch (mode) {
case 'close':
return (
-
+
= props => {
case 'link':
return (
-
+
{BaseContent}
= props => {
default:
return (
-
+
{BaseContent}
@@ -120,3 +112,17 @@ const NoticeBar: FC = props => {
NoticeBar.displayName = 'NoticeBar';
export default NoticeBar;
+
+const WrapComp = ({
+ children,
+ onPress,
+ activeOpacity,
+}: PropsWithChildren>) => {
+ if (onPress)
+ return (
+
+ {children}
+
+ );
+ return <>{children}>;
+};
diff --git a/packages/react-native/src/notify/NotifyRoot.tsx b/packages/react-native/src/notify/NotifyRoot.tsx
index 9d224cec55..bc181f0824 100644
--- a/packages/react-native/src/notify/NotifyRoot.tsx
+++ b/packages/react-native/src/notify/NotifyRoot.tsx
@@ -1,4 +1,4 @@
-import React, { forwardRef, useImperativeHandle } from 'react';
+import React, { forwardRef, useImperativeHandle, useMemo } from 'react';
import { StyleSheet } from 'react-native';
import Animated from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -11,6 +11,7 @@ import Pressable from '../pressable';
import SvgIcon from '../svg-icon';
import Text from '../text';
import { normalShadowOpt, NotifyType } from './constant';
+import { NotifyProps } from './type';
import useNotify from './useNotify';
const { px, hexToRgba } = helpers;
@@ -36,73 +37,83 @@ const NotifyRoot = forwardRef((_, ref) => {
zIndex: 49,
bottom: -insets.bottom,
},
+ wrapper: { borderRadius: normalShadowOpt.radius, backgroundColor: bgColor },
+ });
+
+ return (
+
+
+
+
+
+
+
+ );
+});
+
+export default NotifyRoot;
+
+/**
+ * 渲染Notify内容。分为以下几种情况:
+ * 1. notify的类型不是INFO,这时候直接返回Content
+ * 2. notify类型是INFO:
+ * 1: onPress有值,Content被TouchableOpacity包裹,同时显示right图标;
+ * 如果同时onClose有值,再显示一个close图标,点击可关闭notify
+ * 2: onPress没有值,Contentbu包裹,不显示right图标;
+ * 如果同时onClose有值,再显示一个close图标,点击可关闭notify
+ */
+const Content = ({
+ shadowColor,
+ options,
+ hide,
+}: {
+ hide: () => void;
+ shadowColor: string;
+ options: NotifyProps & { type: NotifyType };
+}) => {
+ const styles = StyleSheet.create({
content: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
- wrapper: { borderRadius: normalShadowOpt.radius, backgroundColor: bgColor },
});
- const Content = (
-
- {options.type === NotifyType.SUCCESS && (
-
-
-
- )}
- {options.type === NotifyType.FAIL && (
-
-
+ const BaseContent = useMemo(
+ () => (
+
+ {options.type === NotifyType.SUCCESS && (
+
+
+
+ )}
+ {options.type === NotifyType.FAIL && (
+
+
+
+ )}
+
+ {options.content}
- )}
-
- {options.content}
-
-
+
+ ),
+ [options.type, options.content, shadowColor]
);
- /**
- * 渲染Notify内容。分为以下几种情况:
- * 1. notify的类型不是INFO,这时候直接返回Content
- * 2. notify类型是INFO:
- * 1: onPress有值,Content被TouchableOpacity包裹,同时显示right图标;
- * 如果同时onClose有值,再显示一个close图标,点击可关闭notify
- * 2: onPress没有值,Contentbu包裹,不显示right图标;
- * 如果同时onClose有值,再显示一个close图标,点击可关闭notify
- */
- const renderContent = () => {
- if (options.type !== NotifyType.INFO) return Content;
-
- if (options.onPress) {
- if (options.onClose) {
- return (
-
- {Content}
- {
- e.stopPropagation();
- hide();
- }}
- >
-
-
-
-
- );
- }
- return (
-
- {Content}
-
-
- );
- }
+ if (options.type !== NotifyType.INFO) return BaseContent;
+ if (options.onPress) {
if (options.onClose) {
return (
-
- {Content}
+
+ {BaseContent}
{
e.stopPropagation();
@@ -111,28 +122,32 @@ const NotifyRoot = forwardRef((_, ref) => {
>
-
+
+
);
}
- return Content;
- };
+ return (
+
+ {BaseContent}
+
+
+ );
+ }
- return (
-
-
-
+ {BaseContent}
+ {
+ e.stopPropagation();
+ hide();
+ }}
>
- {renderContent()}
-
-
-
- );
-});
-
-export default NotifyRoot;
+
+
+
+ );
+ }
+ return BaseContent;
+};
diff --git a/packages/react-native/src/pagination/index.tsx b/packages/react-native/src/pagination/index.tsx
index 870efc5d1f..ec068b94ce 100644
--- a/packages/react-native/src/pagination/index.tsx
+++ b/packages/react-native/src/pagination/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, ReactElement } from 'react';
+import React, { FC, ReactElement, useMemo } from 'react';
import Flex from '../flex';
import Pressable from '../pressable';
@@ -40,10 +40,15 @@ const Pagination: FC = ({
counterRender,
activeOpacity = 0.6,
}) => {
- const { current, setCurrent, totalPage, isFirstPage, isLastPage } = usePagination({ page, pageSize, total });
+ const { current, prev, next, totalPage, isFirstPage, isLastPage } = usePagination({
+ page,
+ pageSize,
+ total,
+ onChange,
+ });
/** 渲染上一页按钮 */
- const renderPrevBtn = () => {
+ const PrevBtn = useMemo(() => {
if (prevButtonRender) {
return prevButtonRender(isFirstPage);
}
@@ -52,10 +57,10 @@ const Pagination: FC = ({
{prevButtonText}
);
- };
+ }, [isFirstPage, prevButtonRender, prevButtonText]);
/** 渲染当前页 */
- const renderCurrent = () => {
+ const Current = useMemo(() => {
if (counterRender) {
return counterRender(current, totalPage);
}
@@ -70,10 +75,10 @@ const Pagination: FC = ({
);
- };
+ }, [counterRender, current, totalPage]);
/** 渲染下一页按钮 */
- const renderNextBtn = () => {
+ const NextBtn = useMemo(() => {
if (nextButtonRender) {
return nextButtonRender(isLastPage);
}
@@ -82,32 +87,16 @@ const Pagination: FC = ({
{nextButtonText}
);
- };
-
- /** 前一页 */
- const prev = () => {
- const perPage = current - 1;
- setCurrent(perPage);
- onChange?.(perPage);
- };
-
- /** 后一页 */
- const next = () => {
- const nextPage = current + 1;
- setCurrent(nextPage);
- onChange?.(nextPage);
- };
+ }, [isLastPage, nextButtonRender, nextButtonText]);
return (
- {renderPrevBtn()}
+ {PrevBtn}
-
- {renderCurrent()}
-
+ {Current}
- {renderNextBtn()}
+ {NextBtn}
);
diff --git a/packages/react-native/src/pagination/usePagination.ts b/packages/react-native/src/pagination/usePagination.ts
index a8c8407812..25925c7f2b 100644
--- a/packages/react-native/src/pagination/usePagination.ts
+++ b/packages/react-native/src/pagination/usePagination.ts
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
-import { useSafeState } from '@td-design/rn-hooks';
+import { useMemoizedFn, useSafeState } from '@td-design/rn-hooks';
import type { PaginationProps } from '.';
@@ -8,7 +8,8 @@ export default function usePagination({
page = 1,
pageSize = 10,
total,
-}: Pick) {
+ onChange,
+}: Pick) {
const [current, setCurrent] = useSafeState(page);
const [totalPage, setTotalPage] = useSafeState(Math.ceil(total / pageSize));
@@ -23,11 +24,27 @@ export default function usePagination({
const isFirstPage = current === 1;
const isLastPage = current === totalPage;
+ /** 前一页 */
+ const prev = () => {
+ const perPage = current - 1;
+ setCurrent(perPage);
+ onChange?.(perPage);
+ };
+
+ /** 后一页 */
+ const next = () => {
+ const nextPage = current + 1;
+ setCurrent(nextPage);
+ onChange?.(nextPage);
+ };
+
return {
current,
- setCurrent,
totalPage,
isFirstPage,
isLastPage,
+
+ prev: useMemoizedFn(prev),
+ next: useMemoizedFn(next),
};
}
diff --git a/packages/react-native/src/pressable/index.tsx b/packages/react-native/src/pressable/index.tsx
index e4781cc8d5..e892899437 100644
--- a/packages/react-native/src/pressable/index.tsx
+++ b/packages/react-native/src/pressable/index.tsx
@@ -29,7 +29,7 @@
* effect is the invocation of `onPress` and `onLongPress` that occur when a
* responder is release while in the "press in" states.
*/
-import React, { PropsWithChildren } from 'react';
+import React, { memo, PropsWithChildren } from 'react';
import { Pressable as RNPressable, PressableProps as RNPressableProps, StyleProp, ViewStyle } from 'react-native';
import helpers from '../helpers';
@@ -58,36 +58,33 @@ export interface PressableProps
}
const { px } = helpers;
-class Pressable extends React.Component> {
- static displayName = 'Pressable';
+function Pressable(props: PropsWithChildren) {
+ const {
+ children,
+ activeOpacity = 0.6,
+ pressOffset = px(20),
+ hitOffset,
+ delayLongPress = 1000,
+ style,
+ ...rest
+ } = props;
- render() {
- const {
- children,
- activeOpacity = 0.6,
- pressOffset = px(20),
- hitOffset,
- delayLongPress = 1000,
- style,
- ...rest
- } = this.props;
+ if (!children) return null;
- if (!children) return null;
-
- return (
- [{ opacity: pressed ? activeOpacity : 1 }, style]}
- {...rest}
- >
- {children}
-
- );
- }
+ return (
+ [{ opacity: pressed ? activeOpacity : 1 }, style]}
+ {...rest}
+ >
+ {children}
+
+ );
}
+Pressable.displayName = 'Pressable';
-export default Pressable;
+export default memo(Pressable);
diff --git a/packages/react-native/src/radio/RadioItem.tsx b/packages/react-native/src/radio/RadioItem.tsx
index 3d4f179768..3ca9f22e3b 100644
--- a/packages/react-native/src/radio/RadioItem.tsx
+++ b/packages/react-native/src/radio/RadioItem.tsx
@@ -1,4 +1,4 @@
-import React, { FC, memo } from 'react';
+import React, { FC, memo, useMemo } from 'react';
import { Keyboard, StyleSheet } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -41,7 +41,7 @@ const RadioItem: FC = ({
list: { width: '100%', flex: 1 },
});
- const renderLabel = () => {
+ const Label = useMemo(() => {
if (typeof label === 'string') {
return (
@@ -50,7 +50,7 @@ const RadioItem: FC = ({
);
}
return label;
- };
+ }, [disabled, label, labelStyle]);
if (!disabled)
return (
@@ -63,7 +63,7 @@ const RadioItem: FC = ({
- {renderLabel()}
+ {Label}
);
@@ -74,7 +74,7 @@ const RadioItem: FC = ({
- {renderLabel()}
+ {Label}
);
diff --git a/packages/react-native/src/result/index.tsx b/packages/react-native/src/result/index.tsx
index d50bc1fead..55a1909fdd 100644
--- a/packages/react-native/src/result/index.tsx
+++ b/packages/react-native/src/result/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, ReactNode } from 'react';
+import React, { FC, memo, ReactNode, useMemo } from 'react';
import { Image, ImageSourcePropType, StyleProp, ViewStyle } from 'react-native';
import { SvgXml } from 'react-native-svg';
@@ -29,7 +29,7 @@ export interface ResultProps {
}
const Result: FC = ({ actions = [], type, title, content, imgSource, containerStyle }) => {
- const renderImgByType = () => {
+ const ImgByType = useMemo(() => {
if (imgSource) return ;
switch (type) {
@@ -42,9 +42,9 @@ const Result: FC = ({ actions = [], type, title, content, imgSource
default:
return null;
}
- };
+ }, [imgSource, type]);
- const renderTitle = () => {
+ const Title = useMemo(() => {
if (!title) return null;
if (typeof title === 'string') {
return (
@@ -54,9 +54,9 @@ const Result: FC = ({ actions = [], type, title, content, imgSource
);
}
return title;
- };
+ }, [title]);
- const renderContent = () => {
+ const Content = useMemo(() => {
if (!content) return null;
if (typeof content === 'string') {
return (
@@ -66,13 +66,13 @@ const Result: FC = ({ actions = [], type, title, content, imgSource
);
}
return content;
- };
+ }, [content]);
return (
- {renderImgByType()}
- {renderTitle()}
- {renderContent()}
+ {ImgByType}
+ {Title}
+ {Content}
{actions.length > 0 && (
{actions.map((action, index) => (
@@ -89,7 +89,7 @@ Result.displayName = 'Result';
export default Result;
-function SuccessImg() {
+const SuccessImg = memo(() => {
const xml = `
);
- };
+ }, [showCancelButton, focused, activeOpacity, theme.spacing.x2, cancelText, onCancel]);
return (
@@ -139,7 +139,7 @@ const SearchBar: FC = props => {
onSubmitEditing={e => onSearch?.(e.nativeEvent.text)}
/>
{/* 取消按钮 */}
- {renderCancelBtn()}
+ {CancelBtn}
);
};
diff --git a/packages/react-native/src/slider/index.tsx b/packages/react-native/src/slider/index.tsx
index 385da87656..2c72dcd117 100644
--- a/packages/react-native/src/slider/index.tsx
+++ b/packages/react-native/src/slider/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, useMemo } from 'react';
import { StyleSheet, TextStyle } from 'react-native';
import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated';
@@ -101,20 +101,26 @@ const Slider: FC = props => {
},
});
- const SliderContent = (
-
-
-
-
-
-
+ const SliderContent = useMemo(
+ () => (
+
+
+
+
+
+
+ ),
+ [width, KNOB_WIDTH, progressStyle, onGestureEvent, knobStyle]
);
if (!showLabel) {
return SliderContent;
}
- const Label = ;
+ const Label = useMemo(
+ () => ,
+ [label, labelStyle]
+ );
if (labelPosition === 'top' || labelPosition === 'bottom') {
return (
diff --git a/packages/react-native/src/svg-icon/IconArrowdown.tsx b/packages/react-native/src/svg-icon/IconArrowdown.tsx
index 5f36f6f59d..67f913f58c 100644
--- a/packages/react-native/src/svg-icon/IconArrowdown.tsx
+++ b/packages/react-native/src/svg-icon/IconArrowdown.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -36,6 +33,4 @@ IconArrowdown.defaultProps = {
size: px(16),
};
-IconArrowdown = React.memo ? React.memo(IconArrowdown) : IconArrowdown;
-
-export default IconArrowdown;
+export default memo(IconArrowdown);
diff --git a/packages/react-native/src/svg-icon/IconBells.tsx b/packages/react-native/src/svg-icon/IconBells.tsx
index 180cf3f198..409914b313 100644
--- a/packages/react-native/src/svg-icon/IconBells.tsx
+++ b/packages/react-native/src/svg-icon/IconBells.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -36,6 +33,4 @@ IconBells.defaultProps = {
size: px(16),
};
-IconBells = React.memo ? React.memo(IconBells) : IconBells;
-
-export default IconBells;
+export default memo(IconBells);
diff --git a/packages/react-native/src/svg-icon/IconCheck.tsx b/packages/react-native/src/svg-icon/IconCheck.tsx
index e964c29b59..af40631557 100644
--- a/packages/react-native/src/svg-icon/IconCheck.tsx
+++ b/packages/react-native/src/svg-icon/IconCheck.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconCheck.defaultProps = {
size: px(16),
};
-IconCheck = React.memo ? React.memo(IconCheck) : IconCheck;
-
-export default IconCheck;
+export default memo(IconCheck);
diff --git a/packages/react-native/src/svg-icon/IconCheckboxChecked.tsx b/packages/react-native/src/svg-icon/IconCheckboxChecked.tsx
index a9ad164022..a5e4047a7c 100644
--- a/packages/react-native/src/svg-icon/IconCheckboxChecked.tsx
+++ b/packages/react-native/src/svg-icon/IconCheckboxChecked.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconCheckboxChecked.defaultProps = {
size: px(16),
};
-IconCheckboxChecked = React.memo ? React.memo(IconCheckboxChecked) : IconCheckboxChecked;
-
-export default IconCheckboxChecked;
+export default memo(IconCheckboxChecked);
diff --git a/packages/react-native/src/svg-icon/IconCheckboxHalfchecked.tsx b/packages/react-native/src/svg-icon/IconCheckboxHalfchecked.tsx
index afc5904e02..dd558414db 100644
--- a/packages/react-native/src/svg-icon/IconCheckboxHalfchecked.tsx
+++ b/packages/react-native/src/svg-icon/IconCheckboxHalfchecked.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconCheckboxHalfchecked.defaultProps = {
size: px(16),
};
-IconCheckboxHalfchecked = React.memo ? React.memo(IconCheckboxHalfchecked) : IconCheckboxHalfchecked;
-
-export default IconCheckboxHalfchecked;
+export default memo(IconCheckboxHalfchecked);
diff --git a/packages/react-native/src/svg-icon/IconCheckboxUnchecked.tsx b/packages/react-native/src/svg-icon/IconCheckboxUnchecked.tsx
index 66986778f7..588586be36 100644
--- a/packages/react-native/src/svg-icon/IconCheckboxUnchecked.tsx
+++ b/packages/react-native/src/svg-icon/IconCheckboxUnchecked.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconCheckboxUnchecked.defaultProps = {
size: px(16),
};
-IconCheckboxUnchecked = React.memo ? React.memo(IconCheckboxUnchecked) : IconCheckboxUnchecked;
-
-export default IconCheckboxUnchecked;
+export default memo(IconCheckboxUnchecked);
diff --git a/packages/react-native/src/svg-icon/IconCheckcircle.tsx b/packages/react-native/src/svg-icon/IconCheckcircle.tsx
index bcb6921638..f761e0e412 100644
--- a/packages/react-native/src/svg-icon/IconCheckcircle.tsx
+++ b/packages/react-native/src/svg-icon/IconCheckcircle.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconCheckcircle.defaultProps = {
size: px(16),
};
-IconCheckcircle = React.memo ? React.memo(IconCheckcircle) : IconCheckcircle;
-
-export default IconCheckcircle;
+export default memo(IconCheckcircle);
diff --git a/packages/react-native/src/svg-icon/IconCheckcircleo.tsx b/packages/react-native/src/svg-icon/IconCheckcircleo.tsx
index 00fa7a1154..c1d23e7acb 100644
--- a/packages/react-native/src/svg-icon/IconCheckcircleo.tsx
+++ b/packages/react-native/src/svg-icon/IconCheckcircleo.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -41,6 +38,4 @@ IconCheckcircleo.defaultProps = {
size: px(16),
};
-IconCheckcircleo = React.memo ? React.memo(IconCheckcircleo) : IconCheckcircleo;
-
-export default IconCheckcircleo;
+export default memo(IconCheckcircleo);
diff --git a/packages/react-native/src/svg-icon/IconClockcircleo.tsx b/packages/react-native/src/svg-icon/IconClockcircleo.tsx
index 1759b18d7f..00bf5b134d 100644
--- a/packages/react-native/src/svg-icon/IconClockcircleo.tsx
+++ b/packages/react-native/src/svg-icon/IconClockcircleo.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -36,6 +33,4 @@ IconClockcircleo.defaultProps = {
size: px(16),
};
-IconClockcircleo = React.memo ? React.memo(IconClockcircleo) : IconClockcircleo;
-
-export default IconClockcircleo;
+export default memo(IconClockcircleo);
diff --git a/packages/react-native/src/svg-icon/IconClose.tsx b/packages/react-native/src/svg-icon/IconClose.tsx
index b7148ec7ae..05a9742a56 100644
--- a/packages/react-native/src/svg-icon/IconClose.tsx
+++ b/packages/react-native/src/svg-icon/IconClose.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconClose.defaultProps = {
size: px(16),
};
-IconClose = React.memo ? React.memo(IconClose) : IconClose;
-
-export default IconClose;
+export default memo(IconClose);
diff --git a/packages/react-native/src/svg-icon/IconClosecircleo.tsx b/packages/react-native/src/svg-icon/IconClosecircleo.tsx
index 27f3cbfc1c..b71c5a68d5 100644
--- a/packages/react-native/src/svg-icon/IconClosecircleo.tsx
+++ b/packages/react-native/src/svg-icon/IconClosecircleo.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconClosecircleo.defaultProps = {
size: px(16),
};
-IconClosecircleo = React.memo ? React.memo(IconClosecircleo) : IconClosecircleo;
-
-export default IconClosecircleo;
+export default memo(IconClosecircleo);
diff --git a/packages/react-native/src/svg-icon/IconDate.tsx b/packages/react-native/src/svg-icon/IconDate.tsx
index 6b4419aa83..94536d5471 100644
--- a/packages/react-native/src/svg-icon/IconDate.tsx
+++ b/packages/react-native/src/svg-icon/IconDate.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -76,6 +73,4 @@ IconDate.defaultProps = {
size: px(16),
};
-IconDate = React.memo ? React.memo(IconDate) : IconDate;
-
-export default IconDate;
+export default memo(IconDate);
diff --git a/packages/react-native/src/svg-icon/IconDown.tsx b/packages/react-native/src/svg-icon/IconDown.tsx
index 3567d1ca3a..693a5592a8 100644
--- a/packages/react-native/src/svg-icon/IconDown.tsx
+++ b/packages/react-native/src/svg-icon/IconDown.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconDown.defaultProps = {
size: px(16),
};
-IconDown = React.memo ? React.memo(IconDown) : IconDown;
-
-export default IconDown;
+export default memo(IconDown);
diff --git a/packages/react-native/src/svg-icon/IconEllipsis.tsx b/packages/react-native/src/svg-icon/IconEllipsis.tsx
index 5ebc6587e9..5e5061ce76 100644
--- a/packages/react-native/src/svg-icon/IconEllipsis.tsx
+++ b/packages/react-native/src/svg-icon/IconEllipsis.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconEllipsis.defaultProps = {
size: px(16),
};
-IconEllipsis = React.memo ? React.memo(IconEllipsis) : IconEllipsis;
-
-export default IconEllipsis;
+export default memo(IconEllipsis);
diff --git a/packages/react-native/src/svg-icon/IconEyeclose.tsx b/packages/react-native/src/svg-icon/IconEyeclose.tsx
index 18efb956aa..15da117764 100644
--- a/packages/react-native/src/svg-icon/IconEyeclose.tsx
+++ b/packages/react-native/src/svg-icon/IconEyeclose.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -51,6 +48,4 @@ IconEyeclose.defaultProps = {
size: px(16),
};
-IconEyeclose = React.memo ? React.memo(IconEyeclose) : IconEyeclose;
-
-export default IconEyeclose;
+export default memo(IconEyeclose);
diff --git a/packages/react-native/src/svg-icon/IconEyeopen.tsx b/packages/react-native/src/svg-icon/IconEyeopen.tsx
index 026bc73a32..c35aa3e16d 100644
--- a/packages/react-native/src/svg-icon/IconEyeopen.tsx
+++ b/packages/react-native/src/svg-icon/IconEyeopen.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -36,6 +33,4 @@ IconEyeopen.defaultProps = {
size: px(16),
};
-IconEyeopen = React.memo ? React.memo(IconEyeopen) : IconEyeopen;
-
-export default IconEyeopen;
+export default memo(IconEyeopen);
diff --git a/packages/react-native/src/svg-icon/IconLeft.tsx b/packages/react-native/src/svg-icon/IconLeft.tsx
index a4d82e88d6..d390997c0e 100644
--- a/packages/react-native/src/svg-icon/IconLeft.tsx
+++ b/packages/react-native/src/svg-icon/IconLeft.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconLeft.defaultProps = {
size: px(16),
};
-IconLeft = React.memo ? React.memo(IconLeft) : IconLeft;
-
-export default IconLeft;
+export default memo(IconLeft);
diff --git a/packages/react-native/src/svg-icon/IconMinus.tsx b/packages/react-native/src/svg-icon/IconMinus.tsx
index 9cfaedcd14..e276b31de6 100644
--- a/packages/react-native/src/svg-icon/IconMinus.tsx
+++ b/packages/react-native/src/svg-icon/IconMinus.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconMinus.defaultProps = {
size: px(16),
};
-IconMinus = React.memo ? React.memo(IconMinus) : IconMinus;
-
-export default IconMinus;
+export default memo(IconMinus);
diff --git a/packages/react-native/src/svg-icon/IconPlus.tsx b/packages/react-native/src/svg-icon/IconPlus.tsx
index 1447ee4a54..3acd38ea24 100644
--- a/packages/react-native/src/svg-icon/IconPlus.tsx
+++ b/packages/react-native/src/svg-icon/IconPlus.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconPlus.defaultProps = {
size: px(16),
};
-IconPlus = React.memo ? React.memo(IconPlus) : IconPlus;
-
-export default IconPlus;
+export default memo(IconPlus);
diff --git a/packages/react-native/src/svg-icon/IconRadioChecked.tsx b/packages/react-native/src/svg-icon/IconRadioChecked.tsx
index 7b5317aaf9..d888106e7e 100644
--- a/packages/react-native/src/svg-icon/IconRadioChecked.tsx
+++ b/packages/react-native/src/svg-icon/IconRadioChecked.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconRadioChecked.defaultProps = {
size: px(16),
};
-IconRadioChecked = React.memo ? React.memo(IconRadioChecked) : IconRadioChecked;
-
-export default IconRadioChecked;
+export default memo(IconRadioChecked);
diff --git a/packages/react-native/src/svg-icon/IconRadioUnchecked.tsx b/packages/react-native/src/svg-icon/IconRadioUnchecked.tsx
index 166c72d306..f75905a557 100644
--- a/packages/react-native/src/svg-icon/IconRadioUnchecked.tsx
+++ b/packages/react-native/src/svg-icon/IconRadioUnchecked.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconRadioUnchecked.defaultProps = {
size: px(16),
};
-IconRadioUnchecked = React.memo ? React.memo(IconRadioUnchecked) : IconRadioUnchecked;
-
-export default IconRadioUnchecked;
+export default memo(IconRadioUnchecked);
diff --git a/packages/react-native/src/svg-icon/IconReload.tsx b/packages/react-native/src/svg-icon/IconReload.tsx
index 8ea4d07243..f8929f84fc 100644
--- a/packages/react-native/src/svg-icon/IconReload.tsx
+++ b/packages/react-native/src/svg-icon/IconReload.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconReload.defaultProps = {
size: px(16),
};
-IconReload = React.memo ? React.memo(IconReload) : IconReload;
-
-export default IconReload;
+export default memo(IconReload);
diff --git a/packages/react-native/src/svg-icon/IconRight.tsx b/packages/react-native/src/svg-icon/IconRight.tsx
index a455f4c875..1da9894db8 100644
--- a/packages/react-native/src/svg-icon/IconRight.tsx
+++ b/packages/react-native/src/svg-icon/IconRight.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconRight.defaultProps = {
size: px(16),
};
-IconRight = React.memo ? React.memo(IconRight) : IconRight;
-
-export default IconRight;
+export default memo(IconRight);
diff --git a/packages/react-native/src/svg-icon/IconSearch.tsx b/packages/react-native/src/svg-icon/IconSearch.tsx
index d753968070..643402f625 100644
--- a/packages/react-native/src/svg-icon/IconSearch.tsx
+++ b/packages/react-native/src/svg-icon/IconSearch.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -36,6 +33,4 @@ IconSearch.defaultProps = {
size: px(16),
};
-IconSearch = React.memo ? React.memo(IconSearch) : IconSearch;
-
-export default IconSearch;
+export default memo(IconSearch);
diff --git a/packages/react-native/src/svg-icon/IconUp.tsx b/packages/react-native/src/svg-icon/IconUp.tsx
index cb1db724ea..a3632032a4 100644
--- a/packages/react-native/src/svg-icon/IconUp.tsx
+++ b/packages/react-native/src/svg-icon/IconUp.tsx
@@ -1,7 +1,4 @@
-/* tslint:disable */
-
-/* eslint-disable */
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { ViewProps } from 'react-native';
import { GProps, SvgXml } from 'react-native-svg';
@@ -31,6 +28,4 @@ IconUp.defaultProps = {
size: px(16),
};
-IconUp = React.memo ? React.memo(IconUp) : IconUp;
-
-export default IconUp;
+export default memo(IconUp);
diff --git a/packages/react-native/src/swipe-row/context.tsx b/packages/react-native/src/swipe-row/context.tsx
index 925cd9045d..3eaa86dc8f 100644
--- a/packages/react-native/src/swipe-row/context.tsx
+++ b/packages/react-native/src/swipe-row/context.tsx
@@ -1,26 +1,34 @@
-import React, { PropsWithChildren, useCallback, useMemo } from 'react';
+import React, { PropsWithChildren, useMemo } from 'react';
-import { usePrevious, useSafeState } from '@td-design/rn-hooks';
+import { useMemoizedFn, usePrevious, useSafeState } from '@td-design/rn-hooks';
export const SwipeRowContext = React.createContext<{
id?: string | number;
changeState: (id: string | number) => void;
+ multiple?: boolean;
}>({
id: undefined,
changeState: (id: string | number) => {
console.log('id', id);
},
+ multiple: false,
});
-export const SwipeRowContextProvider = ({ children }: PropsWithChildren) => {
+export const SwipeRowContextProvider = ({
+ children,
+ multiple,
+}: PropsWithChildren<{
+ /** 是否允许多开 */
+ multiple?: boolean;
+}>) => {
const [currentId, setCurrentId] = useSafeState('');
const previous = usePrevious(currentId);
- const changeState = useCallback((id: string | number) => {
+ const changeState = useMemoizedFn((id: string | number) => {
setCurrentId(id);
- }, []);
+ });
- const value = useMemo(() => ({ changeState, id: previous }), [previous]);
+ const value = useMemo(() => ({ changeState, id: previous, multiple }), [previous, multiple]);
return {children};
};
diff --git a/packages/react-native/src/swipe-row/index.tsx b/packages/react-native/src/swipe-row/index.tsx
index 2a770e0394..96cc09eb70 100644
--- a/packages/react-native/src/swipe-row/index.tsx
+++ b/packages/react-native/src/swipe-row/index.tsx
@@ -78,7 +78,7 @@ const SwipeRow: FC = ({
});
return (
-
+
{props.label}
diff --git a/packages/react-native/src/swipe-row/useSwipeRow.ts b/packages/react-native/src/swipe-row/useSwipeRow.ts
index 7945895754..5d67af2754 100644
--- a/packages/react-native/src/swipe-row/useSwipeRow.ts
+++ b/packages/react-native/src/swipe-row/useSwipeRow.ts
@@ -8,15 +8,15 @@ import { SwipeRowContext } from './context';
export default function useSwipeRow({ anchor, onRemove }: Pick) {
const swipeableRef = useRef(null);
- const { changeState, id } = useContext(SwipeRowContext);
+ const { changeState, id, multiple } = useContext(SwipeRowContext);
const [visible, setVisible] = useSafeState(true);
useEffect(() => {
- if (anchor === id) {
+ if (anchor === id && !multiple) {
swipeableRef.current?.close();
}
- }, [anchor, id]);
+ }, [anchor, id, multiple]);
const handleRemove = async () => {
await onRemove?.();
diff --git a/packages/react-native/src/switch/index.tsx b/packages/react-native/src/switch/index.tsx
index 70b2b11be1..86b2541f9b 100644
--- a/packages/react-native/src/switch/index.tsx
+++ b/packages/react-native/src/switch/index.tsx
@@ -1,4 +1,4 @@
-import React, { forwardRef } from 'react';
+import React, { forwardRef, useMemo } from 'react';
import { StyleSheet, TouchableWithoutFeedback } from 'react-native';
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
import { mix, mixColor } from 'react-native-redash';
@@ -95,7 +95,7 @@ const Switch = forwardRef(
text: { fontSize: HANDLER_SIZE / 2, color: theme.colors.primary200 },
});
- const renderContent = () => {
+ const Content = useMemo(() => {
return (
@@ -111,12 +111,12 @@ const Switch = forwardRef(
);
- };
+ }, [checked, disabled, showText, onText, offText, containerStyle, handlerStyle]);
if (disabled) {
- return renderContent();
+ return Content;
}
- return {renderContent()};
+ return {Content};
}
);
Switch.displayName = 'Switch';
diff --git a/packages/react-native/src/table/Cell.tsx b/packages/react-native/src/table/Cell.tsx
index d8996eede6..61b051b0fa 100644
--- a/packages/react-native/src/table/Cell.tsx
+++ b/packages/react-native/src/table/Cell.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import Box from '../box';
@@ -11,7 +11,7 @@ interface CellProps {
style?: StyleProp;
}
-export const Cell: FC = ({ data, column, style }) => {
+export const Cell: FC = memo(({ data, column, style }) => {
return (
{column.render ? (
@@ -37,4 +37,4 @@ export const Cell: FC = ({ data, column, style }) => {
)}
);
-};
+});
diff --git a/packages/react-native/src/table/Head.tsx b/packages/react-native/src/table/Head.tsx
index 4a00b7adfc..1076318324 100644
--- a/packages/react-native/src/table/Head.tsx
+++ b/packages/react-native/src/table/Head.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useContext, useMemo } from 'react';
+import React, { FC, memo, useContext, useMemo } from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import Box from '../box';
@@ -12,7 +12,7 @@ interface HeadProps {
headerStyle?: StyleProp;
}
-export const Head: FC = ({ headerStyle }) => {
+export const Head: FC = memo(({ headerStyle }) => {
const { columns, cellWidth } = useContext(ColumnContext);
const cellRender = useMemo(() => {
@@ -49,4 +49,4 @@ export const Head: FC = ({ headerStyle }) => {
{cellRender}
);
-};
+});
diff --git a/packages/react-native/src/table/Rows.tsx b/packages/react-native/src/table/Rows.tsx
index dd1c26ee26..d6e6f03c20 100644
--- a/packages/react-native/src/table/Rows.tsx
+++ b/packages/react-native/src/table/Rows.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useContext, useMemo } from 'react';
+import React, { FC, memo, useContext, useMemo } from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import Box from '../box';
@@ -13,7 +13,7 @@ interface RowsProps {
rowStyle?: StyleProp;
}
-export const Rows: FC = ({ data, rowStyle }) => {
+export const Rows: FC = memo(({ data, rowStyle }) => {
const { columns, cellWidth } = useContext(ColumnContext);
const cellRender = useMemo(() => {
@@ -39,4 +39,4 @@ export const Rows: FC = ({ data, rowStyle }) => {
{cellRender}
);
-};
+});
diff --git a/packages/react-native/src/table/index.tsx b/packages/react-native/src/table/index.tsx
index 131447ea82..8700a9a39c 100644
--- a/packages/react-native/src/table/index.tsx
+++ b/packages/react-native/src/table/index.tsx
@@ -48,7 +48,7 @@ function Table>(props: TableProps) {
horizontal
onContentSizeChange={handleLayout}
contentContainerStyle={styles.contentContainer}
- showsHorizontalScrollIndicator={true}
+ showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
scrollEnabled={true}
bounces={false}
@@ -57,6 +57,8 @@ function Table>(props: TableProps) {
scrollEnabled={dataSource.length > 0}
nestedScrollEnabled
stickyHeaderIndices={fixedHeader && showHeader ? [0] : []}
+ showsVerticalScrollIndicator={false}
+ showsHorizontalScrollIndicator={false}
contentContainerStyle={{
flexGrow: 1,
backgroundColor: theme.colors.white,
diff --git a/packages/react-native/src/tag/index.tsx b/packages/react-native/src/tag/index.tsx
index cd11827aac..aea8296bbd 100644
--- a/packages/react-native/src/tag/index.tsx
+++ b/packages/react-native/src/tag/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, useMemo } from 'react';
import { StyleSheet } from 'react-native';
import Svg, { Path } from 'react-native-svg';
@@ -53,6 +53,7 @@ type BaseTagProps = BorderProps &
ColorProps &
LayoutProps &
TypographyProps;
+
const BaseTag = createRestyleComponent([border, backgroundColor, color, layout, typography]);
const { px, ONE_PIXEL } = helpers;
@@ -75,6 +76,35 @@ const Tag: FC = ({
if (closed) return null;
+ const {
+ fontFamily,
+ fontSize = px(12),
+ fontStyle,
+ fontWeight,
+ letterSpacing,
+ lineHeight,
+ textAlign,
+ textDecorationLine,
+ textDecorationStyle,
+ textTransform,
+ color = disabled ? 'disabled' : 'primary100',
+ backgroundColor,
+ borderWidth = ONE_PIXEL,
+ justifyContent = 'center',
+ alignItems = 'center',
+ borderRadius = 'x1',
+ ...rest
+ } = restProps;
+
+ let borderColor = rest.borderColor ?? color;
+ if (ghost && disabled) {
+ borderColor = 'disabled';
+ } else if (checked) {
+ borderColor = 'primary200';
+ }
+
+ const { paddingHorizontal, paddingVertical } = getBySize(size);
+
const styles = StyleSheet.create({
iconBtn: {
position: 'absolute',
@@ -97,20 +127,20 @@ const Tag: FC = ({
});
/** 删除的图标组件 */
- const renderClosableIcon = () => {
+ const ClosableIcon = useMemo(() => {
if (closable && !disabled)
return (
- handleDelete()} style={styles.iconBtn}>
+
);
return null;
- };
+ }, [closable, disabled, styles.iconBtn, styles.iconWrap, theme.colors.white]);
/** 选中的图标组件 */
- const renderCheckedIcon = () => {
+ const CheckedIcon = useMemo(() => {
if (checked)
return (
@@ -123,9 +153,9 @@ const Tag: FC = ({
);
return null;
- };
+ }, [checked, styles.check, theme.colors.primary200]);
- const renderContent = () => (
+ const Content = (
= ({
);
- const {
- fontFamily,
- fontSize = px(12),
- fontStyle,
- fontWeight,
- letterSpacing,
- lineHeight,
- textAlign,
- textDecorationLine,
- textDecorationStyle,
- textTransform,
- color = disabled ? 'disabled' : 'primary100',
- backgroundColor,
- borderWidth = ONE_PIXEL,
- justifyContent = 'center',
- alignItems = 'center',
- borderRadius = 'x1',
- ...rest
- } = restProps;
-
- let borderColor = rest.borderColor ?? color;
- if (ghost && disabled) {
- borderColor = 'disabled';
- } else if (checked) {
- borderColor = 'primary200';
- }
-
- const { paddingHorizontal, paddingVertical } = getBySize(size);
-
if (selectable)
return (
- {renderContent()}
+ {Content}
- {renderClosableIcon()}
- {renderCheckedIcon()}
+ {ClosableIcon}
+ {CheckedIcon}
);
return (
- {renderContent()}
- {renderClosableIcon()}
- {renderCheckedIcon()}
+ {Content}
+ {ClosableIcon}
+ {CheckedIcon}
);
};
diff --git a/packages/react-native/src/text/index.tsx b/packages/react-native/src/text/index.tsx
index e86c11a5c2..fa449e0689 100644
--- a/packages/react-native/src/text/index.tsx
+++ b/packages/react-native/src/text/index.tsx
@@ -1,5 +1,7 @@
-import React, { createElement, memo, PropsWithChildren } from 'react';
+import React, { memo, PropsWithChildren } from 'react';
import { TextProps as RNTextProps } from 'react-native';
+// @ts-ignore
+import { NativeText } from 'react-native/Libraries/Text/TextNativeComponent';
import { createText, TextProps } from '@shopify/restyle';
@@ -7,9 +9,6 @@ import { Theme } from '../theme';
type Props = TextProps & Omit;
-const NativeText = ({ onLongPress, onPress, onPressIn, onPressOut, ...props }: RNTextProps) =>
- createElement('RCTText', props);
-
const BaseText = createText(NativeText);
const Text = memo(({ children, style, ...props }: PropsWithChildren) => {
diff --git a/packages/react-native/src/timeline/HorizontalTimeline.tsx b/packages/react-native/src/timeline/HorizontalTimeline.tsx
index 9b4881d348..201ce1c26d 100644
--- a/packages/react-native/src/timeline/HorizontalTimeline.tsx
+++ b/packages/react-native/src/timeline/HorizontalTimeline.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { memo } from 'react';
import { LayoutChangeEvent, NativeSyntheticEvent, ScrollView, TextLayoutEventData } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -12,48 +12,23 @@ import { TimelineProps, TimelineStepProps } from './type';
const HorizontalTimeline = ({ data, customIcon, lineStyle }: Omit) => {
const [_, { set, get }] = useMap();
+
const handleDateLayout = (e: NativeSyntheticEvent, index: number) => {
const textWidth = e.nativeEvent.lines[0].width;
set(index, Math.floor(textWidth));
};
- const renderDateAndTime = ({ date, time }: TimelineStepProps, index: number) => {
- return (
-
- handleDateLayout(e, index)}>
- {date}
-
-
- {time}
-
-
- );
- };
-
- const renderTitleAndDescription = ({ title, description }: TimelineStepProps) => {
- return (
-
-
- {title}
-
-
- {description}
-
-
- );
- };
-
const renderItem = (item: TimelineStepProps, index: number) => {
return (
- {renderDateAndTime(item, index)}
+ handleDateLayout(e, index)} />
- {renderTitleAndDescription(item)}
+
);
};
@@ -68,34 +43,68 @@ HorizontalTimeline.displayName = 'HorizontalTimeline';
export default HorizontalTimeline;
-const CircleAndLine = ({
- isLast,
- width,
- customIcon,
- lineStyle,
-}: Pick & { isLast: boolean; width: number }) => {
- const theme = useTheme();
- const [iconWidth, setIconWidth] = useSafeState(theme.borderRadii.x2);
-
- const handleLayout = (e: LayoutChangeEvent) => {
- setIconWidth(Math.floor(e.nativeEvent.layout.width));
- };
+const DateAndTime = memo(
+ ({
+ date,
+ time,
+ onLayout,
+ }: TimelineStepProps & { onLayout: (event: NativeSyntheticEvent) => void }) => {
+ return (
+
+
+ {date}
+
+
+ {time}
+
+
+ );
+ }
+);
+const TitleAndDescription = memo(({ title, description }: TimelineStepProps) => {
return (
-
- {customIcon ? (
-
- {customIcon}
-
- ) : (
-
- )}
- {!isLast && }
-
+
+
+ {title}
+
+
+ {description}
+
+
);
-};
+});
+
+const CircleAndLine = memo(
+ ({
+ isLast,
+ width,
+ customIcon,
+ lineStyle,
+ }: Pick & { isLast: boolean; width: number }) => {
+ const theme = useTheme();
+ const [iconWidth, setIconWidth] = useSafeState(theme.borderRadii.x2);
+
+ const handleLayout = (e: LayoutChangeEvent) => {
+ setIconWidth(Math.floor(e.nativeEvent.layout.width));
+ };
+
+ return (
+
+ {customIcon ? (
+
+ {customIcon}
+
+ ) : (
+
+ )}
+ {!isLast && }
+
+ );
+ }
+);
diff --git a/packages/react-native/src/timeline/VerticalTimeline.tsx b/packages/react-native/src/timeline/VerticalTimeline.tsx
index 2587f998d6..d6a03ec01d 100644
--- a/packages/react-native/src/timeline/VerticalTimeline.tsx
+++ b/packages/react-native/src/timeline/VerticalTimeline.tsx
@@ -1,4 +1,4 @@
-import React, { useRef } from 'react';
+import React, { memo, useRef } from 'react';
import { LayoutChangeEvent, ScrollView } from 'react-native';
import { useTheme } from '@shopify/restyle';
@@ -26,36 +26,10 @@ const VerticalTimeline = ({ data, customIcon, lineStyle }: Omit {
- return (
-
-
- {date}
-
-
- {time}
-
-
- );
- };
-
- const renderEvent = ({ title, description }: TimelineStepProps, index: number) => {
- return (
- handleEventLayout(e, index)} flex={1}>
-
- {title}
-
-
- {description}
-
-
- );
- };
-
const renderItem = (item: TimelineStepProps, index: number) => {
return (
- {renderDateAndTime(item)}
+
- {renderEvent(item, index)}
+ handleEventLayout(e, index)} />
);
};
@@ -78,41 +52,79 @@ VerticalTimeline.displayName = 'VerticalTimeline';
export default VerticalTimeline;
-const CircleAndLine = ({
- height,
- isLast,
- titleHeight,
- customIcon,
- lineStyle,
-}: { height: number; isLast: boolean; titleHeight: number } & Pick) => {
- const theme = useTheme();
- const [iconHeight, setIconHeight] = useSafeState(theme.borderRadii.x2);
-
- const handleLayout = (e: LayoutChangeEvent) => {
- setIconHeight(Math.floor(e.nativeEvent.layout.height));
- };
-
+const DateAndTime = memo(({ date, time }: TimelineStepProps) => {
return (
-
- {customIcon ? (
-
- {customIcon}
-
- ) : (
-
- )}
- {!isLast && }
+
+
+ {date}
+
+
+ {time}
+
);
-};
+});
+
+const Event = memo(
+ ({
+ title,
+ description,
+ onLayout,
+ onTitleLayout,
+ }: TimelineStepProps & {
+ onTitleLayout: (event: LayoutChangeEvent) => void;
+ onLayout: (event: LayoutChangeEvent) => void;
+ }) => {
+ return (
+
+
+ {title}
+
+
+ {description}
+
+
+ );
+ }
+);
+
+const CircleAndLine = memo(
+ ({
+ height,
+ isLast,
+ titleHeight,
+ customIcon,
+ lineStyle,
+ }: { height: number; isLast: boolean; titleHeight: number } & Pick) => {
+ const theme = useTheme();
+ const [iconHeight, setIconHeight] = useSafeState(theme.borderRadii.x2);
+
+ const handleLayout = (e: LayoutChangeEvent) => {
+ setIconHeight(Math.floor(e.nativeEvent.layout.height));
+ };
+
+ return (
+
+ {customIcon ? (
+
+ {customIcon}
+
+ ) : (
+
+ )}
+ {!isLast && }
+
+ );
+ }
+);
diff --git a/packages/react-native/src/tooltip/Triangle.tsx b/packages/react-native/src/tooltip/Triangle.tsx
index 2f714e5a0d..720a901692 100644
--- a/packages/react-native/src/tooltip/Triangle.tsx
+++ b/packages/react-native/src/tooltip/Triangle.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { memo } from 'react';
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
import Box from '../box';
@@ -8,7 +8,9 @@ type Props = {
isDown: boolean;
};
-const Triangle = ({ style, isDown }: Props) => ;
+const Triangle = memo(({ style, isDown }: Props) => (
+
+));
const styles = StyleSheet.create({
down: {
diff --git a/packages/react-native/src/tooltip/index.tsx b/packages/react-native/src/tooltip/index.tsx
index d72237dbe1..bccacde772 100644
--- a/packages/react-native/src/tooltip/index.tsx
+++ b/packages/react-native/src/tooltip/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, PropsWithChildren, ReactNode, Reducer, useReducer, useRef } from 'react';
+import React, { FC, memo, PropsWithChildren, ReactNode, Reducer, useMemo, useReducer, useRef } from 'react';
import { Dimensions, LayoutChangeEvent, Modal, Pressable, StyleProp, View, ViewStyle } from 'react-native';
import Box from '../box';
@@ -108,7 +108,7 @@ const Tooltip: FC> = props => {
dispatch({ type: 'toggle' });
};
- const getTooltipStyle = () => {
+ const Content = useMemo(() => {
const { x, y } = getTooltipCoordinate(
offsetX,
offsetY,
@@ -141,30 +141,6 @@ const Tooltip: FC> = props => {
tooltipStyle.top = y;
}
- return { tooltipStyle, pastMiddleLine, pastCenterLine };
- };
-
- const renderPointer = (pastMiddleLine: boolean, pastCenterLine: boolean) => {
- return (
-
-
-
- );
- };
-
- const renderContent = () => {
- const { pastMiddleLine, pastCenterLine, tooltipStyle } = getTooltipStyle();
return (
<>
> = props => {
>
{children}
- {withCaret && renderPointer(pastMiddleLine, pastCenterLine)}
+
{typeof content === 'string' ? (
@@ -191,7 +178,7 @@ const Tooltip: FC> = props => {
>
);
- };
+ }, [offsetX, offsetY, elementWidth, elementHeight, ScreenWidth, ScreenHeight, width, withCaret, backgroundColor]);
const pressableProps = {
[actionType]: toggleTooltip,
@@ -212,7 +199,7 @@ const Tooltip: FC> = props => {
}}
onPress={toggleTooltip}
>
- {renderContent()}
+ {Content}
>
@@ -220,3 +207,44 @@ const Tooltip: FC> = props => {
};
export default Tooltip;
+
+const Pointer = memo(
+ ({
+ withCaret,
+ pastCenterLine,
+ pastMiddleLine,
+ offsetY,
+ offsetX,
+ elementHeight,
+ elementWidth,
+ backgroundColor,
+ }: {
+ withCaret: boolean;
+ pastMiddleLine: boolean;
+ pastCenterLine: boolean;
+ offsetY: number;
+ offsetX: number;
+ elementHeight: number;
+ elementWidth: number;
+ backgroundColor: string;
+ }) => {
+ if (!withCaret) return null;
+
+ return (
+
+
+
+ );
+ }
+);
diff --git a/packages/react-native/src/tree/Checkbox.tsx b/packages/react-native/src/tree/Checkbox.tsx
index f15b8b7f36..20fcaf72cb 100644
--- a/packages/react-native/src/tree/Checkbox.tsx
+++ b/packages/react-native/src/tree/Checkbox.tsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import React, { memo } from 'react';
import { SvgXml } from 'react-native-svg';
import { useTheme } from '@shopify/restyle';
import { Theme } from '../theme';
-export default function Checkbox({ disabled, checked }: { disabled?: boolean; checked: 'all' | 'half' | 'none' }) {
+const Checkbox = memo(({ disabled, checked }: { disabled?: boolean; checked: 'all' | 'half' | 'none' }) => {
const theme = useTheme();
if (checked === 'all') {
@@ -29,4 +29,6 @@ export default function Checkbox({ disabled, checked }: { disabled?: boolean; ch
xml={``}
/>
);
-}
+});
+
+export default Checkbox;
diff --git a/packages/react-native/src/tree/Chevron.tsx b/packages/react-native/src/tree/Chevron.tsx
index 9adfbd2d1d..d42a620d2b 100644
--- a/packages/react-native/src/tree/Chevron.tsx
+++ b/packages/react-native/src/tree/Chevron.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
import { mix } from 'react-native-redash';
@@ -20,4 +20,4 @@ const Chevron: FC<{ progress: Animated.SharedValue }> = ({ progress }) =
);
};
-export default Chevron;
+export default memo(Chevron);
diff --git a/packages/react-native/src/tree/TreeGroup.tsx b/packages/react-native/src/tree/TreeGroup.tsx
index ed39bb07c5..dfdac1f4cc 100644
--- a/packages/react-native/src/tree/TreeGroup.tsx
+++ b/packages/react-native/src/tree/TreeGroup.tsx
@@ -1,4 +1,4 @@
-import { PropsWithChildren } from 'react';
+import { memo, PropsWithChildren } from 'react';
import React from 'react';
import Animated from 'react-native-reanimated';
@@ -15,7 +15,7 @@ import { TreeItemProps, TreeProps } from './type';
import useGroup from './useGroup';
import { useTree } from './useTree';
-export default function TreeGroup({
+function TreeGroup({
id,
text,
disabled,
@@ -80,3 +80,5 @@ export default function TreeGroup({
);
}
+
+export default memo(TreeGroup);
diff --git a/packages/react-native/src/tree/useGroup.ts b/packages/react-native/src/tree/useGroup.ts
index 4584589ba1..f9b0ebe816 100644
--- a/packages/react-native/src/tree/useGroup.ts
+++ b/packages/react-native/src/tree/useGroup.ts
@@ -76,7 +76,7 @@ export default function useGroup({
progress,
checkStatus,
- handleLayout: useMemoizedFn(handleLayout),
+ handleLayout,
handlePress: useMemoizedFn(handlePress),
};
}
diff --git a/packages/react-native/src/white-space/index.tsx b/packages/react-native/src/white-space/index.tsx
index a4e515f4ba..5820530cf7 100644
--- a/packages/react-native/src/white-space/index.tsx
+++ b/packages/react-native/src/white-space/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC, memo } from 'react';
import { useTheme } from '@shopify/restyle';
@@ -16,4 +16,4 @@ const WhiteSpace: FC = ({ size = 'x2', backgroundColor = 'trans
};
WhiteSpace.displayName = 'WhiteSpace';
-export default WhiteSpace;
+export default memo(WhiteSpace);
diff --git a/packages/react-native/src/wing-blank/index.tsx b/packages/react-native/src/wing-blank/index.tsx
index cfb8856ae8..6f27fb466b 100644
--- a/packages/react-native/src/wing-blank/index.tsx
+++ b/packages/react-native/src/wing-blank/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, PropsWithChildren } from 'react';
+import React, { FC, memo, PropsWithChildren } from 'react';
import { BoxProps } from '@shopify/restyle';
@@ -18,4 +18,4 @@ const WingBlank: FC> = ({ children, size = 'x2
};
WingBlank.displayName = 'WingBlank';
-export default WingBlank;
+export default memo(WingBlank);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7933009c53..dda8979ce0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,5 +1,8 @@
lockfileVersion: 5.4
+overrides:
+ '@types/react': 17.0.43
+
importers:
.:
@@ -117,7 +120,7 @@ importers:
'@rollup/plugin-node-resolve': ^15.1.0
'@types/lodash-es': ^4.17.8
'@types/node': ^20.4.4
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
lodash-es: ^4.17.21
rollup: ^3.26.3
@@ -132,7 +135,7 @@ importers:
'@rollup/plugin-node-resolve': 15.1.0_rollup@3.26.3
'@types/lodash-es': 4.17.8
'@types/node': 20.4.4
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
rollup: 3.26.3
rollup-plugin-typescript2: 0.35.0_afuk5ckrta3fepxfxriis2nsxm
@@ -148,7 +151,7 @@ importers:
'@rollup/plugin-node-resolve': ^15.1.0
'@types/color': ^3.0.3
'@types/lodash-es': ^4.17.8
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-dom': ^18.2.7
classnames: ^2.3.2
color: ^4.2.3
@@ -188,7 +191,7 @@ importers:
'@rollup/plugin-node-resolve': 15.1.0_rollup@3.26.3
'@types/color': 3.0.3
'@types/lodash-es': 4.17.8
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-dom': 18.2.7
less: 4.1.3
postcss: 8.4.27
@@ -206,7 +209,7 @@ importers:
'@rollup/plugin-commonjs': ^25.0.3
'@rollup/plugin-node-resolve': ^15.1.0
'@types/lodash-es': ^4.17.8
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-dom': ^18.2.7
echarts: ^5.4.3
echarts-for-react: ^3.0.2
@@ -228,7 +231,7 @@ importers:
'@rollup/plugin-commonjs': 25.0.3_rollup@3.26.3
'@rollup/plugin-node-resolve': 15.1.0_rollup@3.26.3
'@types/lodash-es': 4.17.8
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-dom': 18.2.7
less: 4.1.3
postcss: 8.4.27
@@ -245,7 +248,7 @@ importers:
'@rollup/plugin-commonjs': ^25.0.3
'@rollup/plugin-node-resolve': ^15.1.0
'@types/lodash-es': ^4.17.8
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-dom': ^18.2.7
lodash-es: ^4.17.21
rollup: ^3.26.3
@@ -261,7 +264,7 @@ importers:
'@rollup/plugin-commonjs': 25.0.3_rollup@3.26.3
'@rollup/plugin-node-resolve': 15.1.0_rollup@3.26.3
'@types/lodash-es': 4.17.8
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-dom': 18.2.7
rollup: 3.26.3
rollup-plugin-typescript2: 0.35.0_afuk5ckrta3fepxfxriis2nsxm
@@ -272,7 +275,7 @@ importers:
specifiers:
'@shopify/restyle': 2.4.2
'@td-design/rn-hooks': ^2.7.3
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
rc-field-form: ^1.34.2
react-native-builder-bob: ^0.21.3
@@ -289,7 +292,7 @@ importers:
rc-field-form: 1.34.2
react-native-shadow-2: 7.0.8_react-native-svg@13.10.0
devDependencies:
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-gesture-handler: 2.12.0
@@ -301,21 +304,21 @@ importers:
packages/react-native-alipay:
specifiers:
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
devDependencies:
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
packages/react-native-amap-search:
specifiers:
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
pod-install: ^0.1.38
react-native-builder-bob: ^0.21.3
typescript: ^5.1.6
devDependencies:
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
pod-install: 0.1.38
react-native-builder-bob: 0.21.3
@@ -327,7 +330,7 @@ importers:
'@td-design/react-native': workspace:^5.3.0
'@td-design/react-native-picker': workspace:^2.3.2
'@td-design/rn-hooks': workspace:^2.7.2
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
dayjs: ^1.11.9
react-native-builder-bob: ^0.21.3
@@ -343,7 +346,7 @@ importers:
'@td-design/react-native': link:../react-native
'@td-design/react-native-picker': link:../react-native-picker
'@td-design/rn-hooks': link:../hooks
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-gesture-handler: 2.12.0
@@ -354,13 +357,13 @@ importers:
packages/react-native-echarts:
specifiers:
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
react-native-builder-bob: ^0.21.3
react-native-webview: ^13.2.3
typescript: ^5.1.6
devDependencies:
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-webview: 13.2.3
@@ -371,7 +374,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': workspace:^5.3.0
'@td-design/rn-hooks': workspace:^2.7.2
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: ^0.21.3
react-native-image-picker: ^5.6.0
@@ -380,7 +383,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': link:../react-native
'@td-design/rn-hooks': link:../hooks
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-image-picker: 5.6.0
@@ -391,7 +394,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': workspace:^5.3.0
'@td-design/rn-hooks': workspace:^2.7.2
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
react-native-builder-bob: ^0.21.3
typescript: ^5.1.6
@@ -399,7 +402,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': link:../react-native
'@td-design/rn-hooks': link:../hooks
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
typescript: 5.1.6
@@ -410,7 +413,7 @@ importers:
'@td-design/react-native': workspace:^5.3.0
'@td-design/rn-hooks': workspace:^2.7.2
'@types/lodash-es': ^4.17.8
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
array-tree-filter: ^2.1.0
dayjs: ^1.11.9
@@ -428,7 +431,7 @@ importers:
'@td-design/react-native': link:../react-native
'@td-design/rn-hooks': link:../hooks
'@types/lodash-es': 4.17.8
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
typescript: 5.1.6
@@ -438,7 +441,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': workspace:^5.3.0
'@td-design/rn-hooks': workspace:^2.7.2
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
react-native-builder-bob: ^0.21.3
react-native-gesture-handler: ^2.12.0
@@ -450,7 +453,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': link:../react-native
'@td-design/rn-hooks': link:../hooks
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-gesture-handler: 2.12.0
@@ -463,7 +466,7 @@ importers:
specifiers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': workspace:^5.3.0
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
react-native-builder-bob: ^0.21.3
react-native-svg: ^13.10.0
@@ -471,7 +474,7 @@ importers:
devDependencies:
'@shopify/restyle': 2.4.2
'@td-design/react-native': link:../react-native
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-svg: 13.10.0
@@ -482,7 +485,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': workspace:^5.3.0
'@td-design/rn-hooks': workspace:^2.7.2
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
react-native-builder-bob: ^0.21.3
react-native-linear-gradient: ^2.8.0
@@ -492,7 +495,7 @@ importers:
'@shopify/restyle': 2.4.2
'@td-design/react-native': link:../react-native
'@td-design/rn-hooks': link:../hooks
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-linear-gradient: 2.8.0
@@ -503,7 +506,7 @@ importers:
specifiers:
'@td-design/react-native': workspace:^5.3.0
'@td-design/rn-hooks': workspace:^2.7.2
- '@types/react': ^18.2.15
+ '@types/react': 17.0.43
'@types/react-native': ^0.72.2
color: ^4.2.3
react-native-builder-bob: ^0.21.3
@@ -515,7 +518,7 @@ importers:
devDependencies:
'@td-design/react-native': link:../react-native
'@td-design/rn-hooks': link:../hooks
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-native': 0.72.2
react-native-builder-bob: 0.21.3
react-native-pager-view: 6.2.0
@@ -3373,20 +3376,20 @@ packages:
/@types/react-dom/16.9.19:
resolution: {integrity: sha512-xC8D280Bf6p0zguJ8g62jcEOKZiUbx9sIe6O3tT/lKfR87A7A6g65q13z6D5QUMIa/6yFPkNhqjF5z/VVZEYqQ==}
dependencies:
- '@types/react': 16.14.43
+ '@types/react': 17.0.43
dev: true
/@types/react-dom/18.2.7:
resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==}
dependencies:
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
dev: true
/@types/react-native/0.72.2:
resolution: {integrity: sha512-/eEjr04Zqo7mTMszuSdrLx90+j5nWhDMMOgtnKZfAYyV3RwmlpSb7F17ilmMMxZWJY81n/JZ4e6wdhMJFpjrCg==}
dependencies:
'@react-native/virtualized-lists': 0.72.6
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
transitivePeerDependencies:
- react-native
dev: true
@@ -3395,7 +3398,7 @@ packages:
resolution: {integrity: sha512-WOSetDV3YPxbkVJAdv/bqExJjmcdCi/vpCJh3NfQOy1X15vHMSiMioXIcGekXDJJYhqGUMDo9e337mh508foAA==}
dependencies:
'@types/history': 5.0.0
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-router': 5.1.20
dev: true
@@ -3403,7 +3406,7 @@ packages:
resolution: {integrity: sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w==}
dependencies:
'@types/history': 4.7.11
- '@types/react': 16.14.43
+ '@types/react': 17.0.43
'@types/react-router': 5.1.20
dev: true
@@ -3411,7 +3414,7 @@ packages:
resolution: {integrity: sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==}
dependencies:
'@types/history': 5.0.0
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
'@types/react-router': 5.1.12
dev: true
@@ -3419,26 +3422,18 @@ packages:
resolution: {integrity: sha512-0bhXQwHYfMeJlCh7mGhc0VJTRm0Gk+Z8T00aiP4702mDUuLs9SMhnd2DitpjWFjdOecx2UXtICK14H9iMnziGA==}
dependencies:
'@types/history': 5.0.0
- '@types/react': 18.2.15
+ '@types/react': 17.0.43
dev: true
/@types/react-router/5.1.20:
resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==}
dependencies:
'@types/history': 4.7.11
- '@types/react': 18.2.15
- dev: true
-
- /@types/react/16.14.43:
- resolution: {integrity: sha512-7zdjv7jvoLLQg1tTvpQsm+hyNUMT2mPlNV1+d0I8fbGhkJl82spopMyBlu4wb1dviZAxpGdk5eHu/muacknnfw==}
- dependencies:
- '@types/prop-types': 15.7.5
- '@types/scheduler': 0.16.3
- csstype: 3.1.2
+ '@types/react': 17.0.43
dev: true
- /@types/react/18.2.15:
- resolution: {integrity: sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==}
+ /@types/react/17.0.43:
+ resolution: {integrity: sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==}
dependencies:
'@types/prop-types': 15.7.5
'@types/scheduler': 0.16.3
@@ -3769,7 +3764,7 @@ packages:
react: 16.x || 17.x
react-dom: 16.x || 17.x
dependencies:
- '@types/react': 16.14.43
+ '@types/react': 17.0.43
'@types/react-dom': 16.9.19
'@umijs/runtime': 3.5.41_react@16.14.0
react: 16.14.0
@@ -3782,7 +3777,7 @@ packages:
react: 16.x || 17.x
react-dom: 16.x || 17.x
dependencies:
- '@types/react': 16.14.43
+ '@types/react': 17.0.43
'@types/react-dom': 16.9.19
'@types/react-router-config': 5.0.7
'@umijs/runtime': 3.5.41_react@16.14.0
@@ -3799,7 +3794,7 @@ packages:
react: 16.x || 17.x
react-dom: 16.x || 17.x
dependencies:
- '@types/react': 16.14.43
+ '@types/react': 17.0.43
'@types/react-dom': 16.9.19
'@types/react-router-config': 5.0.7
'@umijs/runtime': 3.5.41_react@17.0.2
@@ -3815,7 +3810,7 @@ packages:
react: 16.x || 17.x
react-dom: 16.x || 17.x
dependencies:
- '@types/react': 16.14.43
+ '@types/react': 17.0.43
'@types/react-dom': 16.9.19
'@types/react-router-config': 5.0.7
'@umijs/runtime': 3.5.41_react@16.14.0