From 045068c1e89f10b93f67f386f186b2689ea44b6d Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 11 Oct 2023 13:35:14 +0200 Subject: [PATCH 1/5] [TS migration] Migrate 'useDragAndDrop.js' hook and 'withEnvironment.js' HOC --- ...withEnvironment.js => withEnvironment.tsx} | 39 ++++++++++--------- .../{useEnvironment.js => useEnvironment.ts} | 10 ++++- src/pages/ShareCodePage.js | 7 +++- 3 files changed, 34 insertions(+), 22 deletions(-) rename src/components/{withEnvironment.js => withEnvironment.tsx} (54%) rename src/hooks/{useEnvironment.js => useEnvironment.ts} (59%) diff --git a/src/components/withEnvironment.js b/src/components/withEnvironment.tsx similarity index 54% rename from src/components/withEnvironment.js rename to src/components/withEnvironment.tsx index 3aa9b86e82c8..6fe84860bb53 100644 --- a/src/components/withEnvironment.js +++ b/src/components/withEnvironment.tsx @@ -1,21 +1,26 @@ -import React, {createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; -import PropTypes from 'prop-types'; +import React, {ComponentType, RefAttributes, ReactNode, createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; +import {ValueOf} from 'type-fest'; import * as Environment from '../libs/Environment/Environment'; import CONST from '../CONST'; import getComponentDisplayName from '../libs/getComponentDisplayName'; -const EnvironmentContext = createContext(null); +type EnvironmentProviderProps = { + /** Actual content wrapped by this component */ + children: ReactNode; +}; -const environmentPropTypes = { +type EnvironmentContextValue = { /** The string value representing the current environment */ - environment: PropTypes.string.isRequired, + environment: ValueOf; /** The string value representing the URL of the current environment */ - environmentURL: PropTypes.string.isRequired, + environmentURL: string; }; -function EnvironmentProvider({children}) { - const [environment, setEnvironment] = useState(CONST.ENVIRONMENT.PRODUCTION); +const EnvironmentContext = createContext(null); + +function EnvironmentProvider({children}: EnvironmentProviderProps) { + const [environment, setEnvironment] = useState>(CONST.ENVIRONMENT.PRODUCTION); const [environmentURL, setEnvironmentURL] = useState(CONST.NEW_EXPENSIFY_URL); useEffect(() => { @@ -24,7 +29,7 @@ function EnvironmentProvider({children}) { }, []); const contextValue = useMemo( - () => ({ + (): EnvironmentContextValue => ({ environment, environmentURL, }), @@ -35,14 +40,11 @@ function EnvironmentProvider({children}) { } EnvironmentProvider.displayName = 'EnvironmentProvider'; -EnvironmentProvider.propTypes = { - /** Actual content wrapped by this component */ - children: PropTypes.node.isRequired, -}; -export default function withEnvironment(WrappedComponent) { - const WithEnvironment = forwardRef((props, ref) => { - const {environment, environmentURL} = useContext(EnvironmentContext); +// eslint-disable-next-line @typescript-eslint/naming-convention +export default function withEnvironment(WrappedComponent: ComponentType) { + const WithEnvironment: ComponentType>> = forwardRef((props, ref) => { + const {environment, environmentURL} = useContext(EnvironmentContext) ?? {}; return ( & { + isProduction: boolean; + isDevelopment: boolean; +}; + +export default function useEnvironment(): UseEnvironment { + const {environment, environmentURL} = useContext(EnvironmentContext) ?? {}; return { environment, environmentURL, diff --git a/src/pages/ShareCodePage.js b/src/pages/ShareCodePage.js index e6d36ebc7070..f0f0ef7d09fd 100644 --- a/src/pages/ShareCodePage.js +++ b/src/pages/ShareCodePage.js @@ -1,6 +1,7 @@ import React from 'react'; import {View, ScrollView} from 'react-native'; import _ from 'underscore'; +import PropTypes from 'prop-types'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; import Navigation from '../libs/Navigation/Navigation'; @@ -20,16 +21,18 @@ import CONST from '../CONST'; import ContextMenuItem from '../components/ContextMenuItem'; import * as UserUtils from '../libs/UserUtils'; import ROUTES from '../ROUTES'; -import withEnvironment, {environmentPropTypes} from '../components/withEnvironment'; +import withEnvironment from '../components/withEnvironment'; import * as Url from '../libs/Url'; const propTypes = { /** The report currently being looked at */ report: reportPropTypes, + /** The string value representing the URL of the current environment */ + environmentURL: PropTypes.string.isRequired, + ...withLocalizePropTypes, ...withCurrentUserPersonalDetailsPropTypes, - ...environmentPropTypes, }; const defaultProps = { From 70c8123e40e181c694755a7bfec0a90e53f8b856 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 11 Oct 2023 14:30:58 +0200 Subject: [PATCH 2/5] Update getComponentDisplayName to accept types with generics --- src/components/withEnvironment.tsx | 2 +- src/libs/getComponentDisplayName.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/withEnvironment.tsx b/src/components/withEnvironment.tsx index 6fe84860bb53..35e4d291da34 100644 --- a/src/components/withEnvironment.tsx +++ b/src/components/withEnvironment.tsx @@ -56,7 +56,7 @@ export default function withEnvironment(component: ComponentType): string { return component.displayName ?? component.name ?? 'Component'; } From ce478db6504993f6c6216803bc1d5f7ef2e48790 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 11 Oct 2023 14:39:02 +0200 Subject: [PATCH 3/5] Put EnvironmentValue into a separate type --- src/components/withEnvironment.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/withEnvironment.tsx b/src/components/withEnvironment.tsx index 35e4d291da34..5476c0562109 100644 --- a/src/components/withEnvironment.tsx +++ b/src/components/withEnvironment.tsx @@ -9,9 +9,11 @@ type EnvironmentProviderProps = { children: ReactNode; }; +type EnvironmentValue = ValueOf; + type EnvironmentContextValue = { /** The string value representing the current environment */ - environment: ValueOf; + environment: EnvironmentValue; /** The string value representing the URL of the current environment */ environmentURL: string; @@ -20,7 +22,7 @@ type EnvironmentContextValue = { const EnvironmentContext = createContext(null); function EnvironmentProvider({children}: EnvironmentProviderProps) { - const [environment, setEnvironment] = useState>(CONST.ENVIRONMENT.PRODUCTION); + const [environment, setEnvironment] = useState(CONST.ENVIRONMENT.PRODUCTION); const [environmentURL, setEnvironmentURL] = useState(CONST.NEW_EXPENSIFY_URL); useEffect(() => { From 41c2e6814314d63ed9e43910629538737c6b7840 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 16 Oct 2023 13:14:30 +0200 Subject: [PATCH 4/5] Update withEnvironment HOC typing --- .eslintrc.js | 2 +- src/components/withEnvironment.tsx | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 75a74ed371c4..83e9479ce0c4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -116,7 +116,7 @@ module.exports = { }, { selector: ['parameter', 'method'], - format: ['camelCase'], + format: ['camelCase', 'PascalCase'], }, ], '@typescript-eslint/ban-types': [ diff --git a/src/components/withEnvironment.tsx b/src/components/withEnvironment.tsx index 5476c0562109..9ea464fafffd 100644 --- a/src/components/withEnvironment.tsx +++ b/src/components/withEnvironment.tsx @@ -1,4 +1,4 @@ -import React, {ComponentType, RefAttributes, ReactNode, createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; +import React, {ComponentType, RefAttributes, ReactNode, ForwardedRef, createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; import {ValueOf} from 'type-fest'; import * as Environment from '../libs/Environment/Environment'; import CONST from '../CONST'; @@ -21,7 +21,7 @@ type EnvironmentContextValue = { const EnvironmentContext = createContext(null); -function EnvironmentProvider({children}: EnvironmentProviderProps) { +function EnvironmentProvider({children}: EnvironmentProviderProps): React.JSX.Element { const [environment, setEnvironment] = useState(CONST.ENVIRONMENT.PRODUCTION); const [environmentURL, setEnvironmentURL] = useState(CONST.NEW_EXPENSIFY_URL); @@ -43,24 +43,25 @@ function EnvironmentProvider({children}: EnvironmentProviderProps) { EnvironmentProvider.displayName = 'EnvironmentProvider'; -// eslint-disable-next-line @typescript-eslint/naming-convention -export default function withEnvironment(WrappedComponent: ComponentType) { - const WithEnvironment: ComponentType>> = forwardRef((props, ref) => { +export default function withEnvironment( + WrappedComponent: ComponentType>, +): (props: Omit & React.RefAttributes) => React.JSX.Element | null { + function WithEnvironment(props: Omit, ref: ForwardedRef): React.JSX.Element { const {environment, environmentURL} = useContext(EnvironmentContext) ?? {}; return ( ); - }); + } WithEnvironment.displayName = `withEnvironment(${getComponentDisplayName(WrappedComponent)})`; - return WithEnvironment; + return forwardRef(WithEnvironment); } export {EnvironmentContext, EnvironmentProvider}; From c1a3297ce156a156cc96874fc0d596bb7be8fda4 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 16 Oct 2023 13:38:09 +0200 Subject: [PATCH 5/5] Replace React.JSX.Element with ReactElement --- src/components/withEnvironment.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/withEnvironment.tsx b/src/components/withEnvironment.tsx index 9ea464fafffd..0f065eac68fe 100644 --- a/src/components/withEnvironment.tsx +++ b/src/components/withEnvironment.tsx @@ -1,4 +1,4 @@ -import React, {ComponentType, RefAttributes, ReactNode, ForwardedRef, createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; +import React, {ComponentType, RefAttributes, ReactNode, ForwardedRef, ReactElement, createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; import {ValueOf} from 'type-fest'; import * as Environment from '../libs/Environment/Environment'; import CONST from '../CONST'; @@ -21,7 +21,7 @@ type EnvironmentContextValue = { const EnvironmentContext = createContext(null); -function EnvironmentProvider({children}: EnvironmentProviderProps): React.JSX.Element { +function EnvironmentProvider({children}: EnvironmentProviderProps): ReactElement { const [environment, setEnvironment] = useState(CONST.ENVIRONMENT.PRODUCTION); const [environmentURL, setEnvironmentURL] = useState(CONST.NEW_EXPENSIFY_URL); @@ -45,8 +45,8 @@ EnvironmentProvider.displayName = 'EnvironmentProvider'; export default function withEnvironment( WrappedComponent: ComponentType>, -): (props: Omit & React.RefAttributes) => React.JSX.Element | null { - function WithEnvironment(props: Omit, ref: ForwardedRef): React.JSX.Element { +): (props: Omit & React.RefAttributes) => ReactElement | null { + function WithEnvironment(props: Omit, ref: ForwardedRef): ReactElement { const {environment, environmentURL} = useContext(EnvironmentContext) ?? {}; return (