Fix memory leak on mobile web tab navigation (#2021)

* Add navigationAction prop to Link

* Bottom bar should use navigate() action
zio/stable
dan 2023-11-28 22:48:00 +00:00 committed by GitHub
parent bb9d340d42
commit b778017000
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 6 deletions

View File

@ -46,6 +46,7 @@ interface Props extends ComponentProps<typeof TouchableOpacity> {
noFeedback?: boolean noFeedback?: boolean
asAnchor?: boolean asAnchor?: boolean
anchorNoUnderline?: boolean anchorNoUnderline?: boolean
navigationAction?: 'push' | 'replace' | 'navigate'
} }
export const Link = memo(function Link({ export const Link = memo(function Link({
@ -58,6 +59,7 @@ export const Link = memo(function Link({
asAnchor, asAnchor,
accessible, accessible,
anchorNoUnderline, anchorNoUnderline,
navigationAction,
...props ...props
}: Props) { }: Props) {
const {closeModal} = useModalControls() const {closeModal} = useModalControls()
@ -67,10 +69,16 @@ export const Link = memo(function Link({
const onPress = React.useCallback( const onPress = React.useCallback(
(e?: Event) => { (e?: Event) => {
if (typeof href === 'string') { if (typeof href === 'string') {
return onPressInner(closeModal, navigation, sanitizeUrl(href), e) return onPressInner(
closeModal,
navigation,
sanitizeUrl(href),
navigationAction,
e,
)
} }
}, },
[closeModal, navigation, href], [closeModal, navigation, navigationAction, href],
) )
if (noFeedback) { if (noFeedback) {
@ -146,6 +154,7 @@ export const TextLink = memo(function TextLink({
title, title,
onPress, onPress,
warnOnMismatchingLabel, warnOnMismatchingLabel,
navigationAction,
...orgProps ...orgProps
}: { }: {
testID?: string testID?: string
@ -158,6 +167,7 @@ export const TextLink = memo(function TextLink({
dataSet?: any dataSet?: any
title?: string title?: string
warnOnMismatchingLabel?: boolean warnOnMismatchingLabel?: boolean
navigationAction?: 'push' | 'replace' | 'navigate'
} & TextProps) { } & TextProps) {
const {...props} = useLinkProps({to: sanitizeUrl(href)}) const {...props} = useLinkProps({to: sanitizeUrl(href)})
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
@ -185,7 +195,13 @@ export const TextLink = memo(function TextLink({
// @ts-ignore function signature differs by platform -prf // @ts-ignore function signature differs by platform -prf
return onPress() return onPress()
} }
return onPressInner(closeModal, navigation, sanitizeUrl(href), e) return onPressInner(
closeModal,
navigation,
sanitizeUrl(href),
navigationAction,
e,
)
}, },
[ [
onPress, onPress,
@ -195,6 +211,7 @@ export const TextLink = memo(function TextLink({
href, href,
text, text,
warnOnMismatchingLabel, warnOnMismatchingLabel,
navigationAction,
], ],
) )
const hrefAttrs = useMemo(() => { const hrefAttrs = useMemo(() => {
@ -241,6 +258,7 @@ interface TextLinkOnWebOnlyProps extends TextProps {
accessibilityLabel?: string accessibilityLabel?: string
accessibilityHint?: string accessibilityHint?: string
title?: string title?: string
navigationAction?: 'push' | 'replace' | 'navigate'
} }
export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
testID, testID,
@ -250,6 +268,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
text, text,
numberOfLines, numberOfLines,
lineHeight, lineHeight,
navigationAction,
...props ...props
}: TextLinkOnWebOnlyProps) { }: TextLinkOnWebOnlyProps) {
if (isWeb) { if (isWeb) {
@ -263,6 +282,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
numberOfLines={numberOfLines} numberOfLines={numberOfLines}
lineHeight={lineHeight} lineHeight={lineHeight}
title={props.title} title={props.title}
navigationAction={navigationAction}
{...props} {...props}
/> />
) )
@ -296,6 +316,7 @@ function onPressInner(
closeModal = () => {}, closeModal = () => {},
navigation: NavigationProp, navigation: NavigationProp,
href: string, href: string,
navigationAction: 'push' | 'replace' | 'navigate' = 'push',
e?: Event, e?: Event,
) { ) {
let shouldHandle = false let shouldHandle = false
@ -328,8 +349,18 @@ function onPressInner(
} else { } else {
closeModal() // close any active modals closeModal() // close any active modals
if (navigationAction === 'push') {
// @ts-ignore we're not able to type check on this one -prf // @ts-ignore we're not able to type check on this one -prf
navigation.dispatch(StackActions.push(...router.matchPath(href))) navigation.dispatch(StackActions.push(...router.matchPath(href)))
} else if (navigationAction === 'replace') {
// @ts-ignore we're not able to type check on this one -prf
navigation.dispatch(StackActions.replace(...router.matchPath(href)))
} else if (navigationAction === 'navigate') {
// @ts-ignore we're not able to type check on this one -prf
navigation.navigate(...router.matchPath(href))
} else {
throw Error('Unsupported navigator action.')
}
} }
} }
} }

View File

@ -137,7 +137,7 @@ const NavItem: React.FC<{
: isTab(currentRoute.name, routeName) : isTab(currentRoute.name, routeName)
return ( return (
<Link href={href} style={styles.ctrl}> <Link href={href} style={styles.ctrl} navigationAction="navigate">
{children({isActive})} {children({isActive})}
</Link> </Link>
) )