Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[No QA] [TS migration] Migrate 'withNavigationFallback.js' HOC to TypeScript #30072

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions src/components/withNavigationFallback.js

This file was deleted.

43 changes: 43 additions & 0 deletions src/components/withNavigationFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, {ComponentType, RefAttributes, ForwardedRef, ReactElement, forwardRef, useContext, useMemo} from 'react';
import {NavigationContext} from '@react-navigation/core';
import {NavigationProp} from '@react-navigation/native';
import {ParamListBase} from '@react-navigation/routers';
import getComponentDisplayName from '../libs/getComponentDisplayName';

type AddListenerCallback = () => void;

type RemoveListenerCallback = () => void;
VickyStash marked this conversation as resolved.
Show resolved Hide resolved

type NavigationContextValue = {
isFocused: () => boolean;
addListener: () => AddListenerCallback;
removeListener: () => RemoveListenerCallback;
};

export default function <TProps, TRef>(WrappedComponent: ComponentType<TProps & RefAttributes<TRef>>): (props: TProps & RefAttributes<TRef>) => ReactElement | null {
function WithNavigationFallback(props: TProps, ref: ForwardedRef<TRef>) {
const context = useContext(NavigationContext);

const navigationContextValue: NavigationContextValue = useMemo(() => ({isFocused: () => true, addListener: () => () => {}, removeListener: () => () => {}}), []);
VickyStash marked this conversation as resolved.
Show resolved Hide resolved

return context ? (
<WrappedComponent
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={ref}
/>
) : (
<NavigationContext.Provider value={navigationContextValue as unknown as NavigationProp<ParamListBase>}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this assertion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabioh8010 Because NavigationContext.Provider value is expected to be of type NavigationProp<ParamListBase>, but to make our navigationContextValue be of this type, we need to add a lot of methods like navigate, reset, goBack, etc. If you have any ideas on how to improve it, please let me know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to understand why do we pass only this values in the first place 🤔. It seems that only Button component uses this HOC, could you check what props from this HOC are really being injected in the component?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabioh8010 Let me provide you with a little bit more context.
This HOC is a workaround for cases when Button/Composer is used outside of the Navigation container. isFocused param is used in button, addListener and removeListener are used in Composer.
It's the second PR for this file to migrate, that was the first.
In the previous one, we had a suggestion that this HOC isn't necessary anymore and removed it. It caused regressions.
This time I investigated it more careful, and it's not possible to get rid of this HOC, because ErrorBoundary is located outside of the NavigationContainer an has a fallback component GenericErrorPage which has Buttons inside. So without this HOC usage it'll crash.

For more details, see
#24953 (comment)
#24953 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see, I guess we have no other option then

<WrappedComponent
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={ref}
/>
</NavigationContext.Provider>
);
}

WithNavigationFallback.displayName = `WithNavigationFocusWithFallback(${getComponentDisplayName(WrappedComponent)})`;

return forwardRef(WithNavigationFallback);
}
Loading