Browse Source

chore(js): Avoid React.FC function typing (#47060)

In react 18 this type loses it's `children` prop. This change avoids
using it and defines props regularly.

As a double whammy, this makes it easy when we pick a component function
style with the `react/function-component-definition` rule.
Evan Purkhiser 1 year ago
parent
commit
5b51d90cf2

+ 4 - 10
static/app/components/banner.tsx

@@ -32,6 +32,7 @@ type BannerWrapperProps = {
 };
 
 type Props = BannerWrapperProps & {
+  children?: React.ReactNode;
   className?: string;
   dismissKey?: string;
   isDismissable?: boolean;
@@ -39,14 +40,7 @@ type Props = BannerWrapperProps & {
   title?: string;
 };
 
-type BannerType = React.FC<Props> & {
-  /**
-   * Helper function to hide banners outside of their usage
-   */
-  dismiss: typeof dismissBanner;
-};
-
-const Banner: BannerType = ({
+function Banner({
   title,
   subtitle,
   isDismissable = true,
@@ -55,7 +49,7 @@ const Banner: BannerType = ({
   backgroundImg,
   backgroundComponent,
   children,
-}) => {
+}: Props) {
   const [dismissed, dismiss] = useDismissable(dismissKey);
 
   if (dismissed) {
@@ -73,7 +67,7 @@ const Banner: BannerType = ({
       </BannerContent>
     </BannerWrapper>
   );
-};
+}
 
 Banner.dismiss = dismissBanner;
 

+ 6 - 6
static/app/components/calendar/index.tsx

@@ -9,7 +9,7 @@ import type {DateRangePickerProps} from './dateRangePicker';
 const LazyDatePicker = lazy(() => import('./datePicker'));
 const LazyDateRangePicker = lazy(() => import('./dateRangePicker'));
 
-const CalendarSuspenseWrapper: React.FC = ({children}) => {
+function CalendarSuspenseWrapper({children}: {children: React.ReactNode}) {
   return (
     <Suspense
       fallback={
@@ -21,20 +21,20 @@ const CalendarSuspenseWrapper: React.FC = ({children}) => {
       {children}
     </Suspense>
   );
-};
+}
 
-export const DatePicker = (props: DatePickerProps) => {
+export function DatePicker(props: DatePickerProps) {
   return (
     <CalendarSuspenseWrapper>
       <LazyDatePicker {...props} />
     </CalendarSuspenseWrapper>
   );
-};
+}
 
-export const DateRangePicker = (props: DateRangePickerProps) => {
+export function DateRangePicker(props: DateRangePickerProps) {
   return (
     <CalendarSuspenseWrapper>
       <LazyDateRangePicker {...props} />
     </CalendarSuspenseWrapper>
   );
-};
+}

+ 4 - 3
static/app/components/collapsible.tsx

@@ -13,6 +13,7 @@ type ExpandButtonRenderProps = {
 };
 
 type Props = {
+  children: React.ReactNode;
   collapseButton?: (props: CollapseButtonRenderProps) => React.ReactNode;
   expandButton?: (props: ExpandButtonRenderProps) => React.ReactNode;
   maxVisibleItems?: number;
@@ -21,12 +22,12 @@ type Props = {
 /**
  * This component is used to show first X items and collapse the rest
  */
-const Collapsible: React.FC<Props> = ({
+function Collapsible({
   collapseButton,
   expandButton,
   maxVisibleItems = 5,
   children,
-}) => {
+}: Props) {
   const [isCollapsed, setCollapsed] = useState(true);
   const handleCollapseToggle = () => setCollapsed(!isCollapsed);
 
@@ -61,6 +62,6 @@ const Collapsible: React.FC<Props> = ({
       {numberOfHiddenItems === 0 && collapseButton?.({onCollapse: handleCollapseToggle})}
     </Fragment>
   );
-};
+}
 
 export default Collapsible;

+ 2 - 9
static/app/components/globalModal/components.tsx

@@ -81,19 +81,13 @@ interface ClosableHeaderProps extends React.HTMLAttributes<HTMLHeadingElement> {
  * Creates a ModalHeader that includes props to enable the close button
  */
 const makeClosableHeader = (closeModal: () => void) => {
-  const ClosableHeader: React.FC<ClosableHeaderProps> = ({
-    closeButton,
-    children,
-    ...props
-  }) => (
+  const ClosableHeader = ({closeButton, children, ...props}: ClosableHeaderProps) => (
     <ModalHeader {...props}>
       {children}
       {closeButton ? <CloseButton onClick={closeModal} /> : null}
     </ModalHeader>
   );
 
-  ClosableHeader.displayName = 'Header';
-
   return ClosableHeader;
 };
 
@@ -101,8 +95,7 @@ const makeClosableHeader = (closeModal: () => void) => {
  * Creates a CloseButton component that is connected to the provided closeModal trigger
  */
 const makeCloseButton =
-  (closeModal: () => void): React.FC<Omit<ButtonProps, 'aria-label'>> =>
-  props =>
+  (closeModal: () => void) => (props: Omit<ButtonProps, 'aria-label'>) =>
     <CloseButton {...props} onClick={closeModal} />;
 
 export {makeClosableHeader, makeCloseButton, ModalBody, ModalFooter};

+ 1 - 0
static/app/components/issues/compactIssue.tsx

@@ -81,6 +81,7 @@ type Props = {
   api: Client;
   id: string;
   organization: Organization;
+  children?: React.ReactNode;
   data?: BaseGroup;
   eventId?: string;
 };

+ 2 - 2
static/app/routes.tsx

@@ -56,11 +56,11 @@ export function makeLazyloadComponent<C extends React.ComponentType<any>>(
   resolve: () => Promise<{default: C}>
 ) {
   // XXX: Assign the component to a variable so it has a displayname
-  const RouteLazyLoad: React.FC<React.ComponentProps<C>> = props => {
+  function RouteLazyLoad(props: React.ComponentProps<C>) {
     // we can use this hook to set the organization as it's
     // a child of the organization context
     return <SafeLazyLoad {...props} component={resolve} />;
-  };
+  }
 
   return RouteLazyLoad;
 }

+ 2 - 2
static/app/utils/routeAnalytics/withRouteAnalytics.tsx

@@ -11,10 +11,10 @@ type WrappedProps<P> = Omit<P, keyof WithRouteAnalyticsProps> &
 const withRouteAnalytics = <P extends WithRouteAnalyticsProps>(
   WrappedComponent: React.ComponentType<P>
 ) => {
-  const ComponentWithRouteAnalytics: React.FC<WrappedProps<P>> = props => {
+  function ComponentWithRouteAnalytics(props: WrappedProps<P>) {
     const routeAnalyticsContext = useContext(RouteAnalyticsContext);
     return <WrappedComponent {...(props as P)} {...routeAnalyticsContext} />;
-  };
+  }
   ComponentWithRouteAnalytics.displayName = `withRouteAnalytics(${getDisplayName(
     WrappedComponent
   )})`;

+ 1 - 1
static/app/utils/withApi.tsx

@@ -21,7 +21,7 @@ const withApi = <P extends InjectedApiProps>(
   WrappedComponent: React.ComponentType<P>,
   options: Parameters<typeof useApi>[0] = {}
 ) => {
-  const WithApi: React.FC<WrappedProps<P>> = ({api: propsApi, ...props}) => {
+  const WithApi = ({api: propsApi, ...props}: WrappedProps<P>) => {
     const api = useApi({api: propsApi, ...options});
 
     return <WrappedComponent {...(props as P)} api={api} />;

+ 2 - 2
static/app/utils/withConfig.tsx

@@ -16,12 +16,12 @@ function withConfig<P extends InjectedConfigProps>(
 ) {
   type Props = Omit<P, keyof InjectedConfigProps> & Partial<InjectedConfigProps>;
 
-  const Wrapper: React.FC<Props> = props => {
+  function Wrapper(props: Props) {
     const config = useLegacyStore(ConfigStore);
     const allProps = {config, ...props} as P;
 
     return <WrappedComponent {...allProps} />;
-  };
+  }
 
   Wrapper.displayName = `withConfig(${getDisplayName(WrappedComponent)})`;
 

+ 2 - 2
static/app/utils/withPageFilters.tsx

@@ -17,7 +17,7 @@ function withPageFilters<P extends InjectedPageFiltersProps>(
 ) {
   type Props = Omit<P, keyof InjectedPageFiltersProps> & InjectedPageFiltersProps;
 
-  const WithPageFilters: React.FC<Props> = props => {
+  function WithPageFilters(props: Props) {
     const {selection, isReady: isGlobalSelectionReady} = usePageFilters();
 
     const selectionProps = {
@@ -26,7 +26,7 @@ function withPageFilters<P extends InjectedPageFiltersProps>(
     };
 
     return <WrappedComponent {...selectionProps} {...(props as P)} />;
-  };
+  }
 
   const displayName = getDisplayName(WrappedComponent);
   WithPageFilters.displayName = `withPageFilters(${displayName})`;

Some files were not shown because too many files changed in this diff