diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 566b6c709423..d5d5f4903888 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -207,7 +207,7 @@ function AddPlaidBankAccount({ // Handle Plaid login errors (will potentially reset plaid token and item depending on the error) if (event === 'ERROR') { Log.hmmm('[PlaidLink] Error: ', metadata); - if (bankAccountID && metadata.error_code) { + if (bankAccountID && metadata && metadata.error_code) { BankAccounts.handlePlaidError(bankAccountID, metadata.error_code, metadata.error_message, metadata.request_id); } } diff --git a/src/components/PlaidLink/index.native.js b/src/components/PlaidLink/index.native.js deleted file mode 100644 index 7d995d03926b..000000000000 --- a/src/components/PlaidLink/index.native.js +++ /dev/null @@ -1,42 +0,0 @@ -import {useEffect} from 'react'; -import {dismissLink, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; -import Log from '@libs/Log'; -import CONST from '@src/CONST'; -import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; - -function PlaidLink(props) { - useDeepLinkRedirector(); - usePlaidEmitter((event) => { - Log.info('[PlaidLink] Handled Plaid Event: ', false, event); - props.onEvent(event.eventName, event.metadata); - }); - useEffect(() => { - props.onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); - openLink({ - tokenConfig: { - token: props.token, - }, - onSuccess: ({publicToken, metadata}) => { - props.onSuccess({publicToken, metadata}); - }, - onExit: (exitError, metadata) => { - Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); - props.onExit(); - }, - }); - - return () => { - dismissLink(); - }; - - // We generally do not need to include the token as a dependency here as it is only provided once via props and should not change - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - return null; -} - -PlaidLink.propTypes = plaidLinkPropTypes; -PlaidLink.defaultProps = plaidLinkDefaultProps; -PlaidLink.displayName = 'PlaidLink'; - -export default PlaidLink; diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx new file mode 100644 index 000000000000..02d4669bc861 --- /dev/null +++ b/src/components/PlaidLink/index.native.tsx @@ -0,0 +1,41 @@ +import {useEffect} from 'react'; +import {dismissLink, LinkEvent, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; +import Log from '@libs/Log'; +import CONST from '@src/CONST'; +import PlaidLinkProps from './types'; + +function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { + useDeepLinkRedirector(); + usePlaidEmitter((event: LinkEvent) => { + Log.info('[PlaidLink] Handled Plaid Event: ', false, {...event}); + onEvent(event.eventName, event.metadata); + }); + useEffect(() => { + onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); + openLink({ + tokenConfig: { + token, + noLoadingState: false, + }, + onSuccess: ({publicToken, metadata}) => { + onSuccess({publicToken, metadata}); + }, + onExit: ({error, metadata}) => { + Log.info('[PlaidLink] Exit: ', false, {error, metadata}); + onExit(); + }, + }); + + return () => { + dismissLink(); + }; + + // We generally do not need to include the token as a dependency here as it is only provided once via props and should not change + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return null; +} + +PlaidLink.displayName = 'PlaidLink'; + +export default PlaidLink; diff --git a/src/components/PlaidLink/index.js b/src/components/PlaidLink/index.tsx similarity index 70% rename from src/components/PlaidLink/index.js rename to src/components/PlaidLink/index.tsx index 790206f34ce7..2109771473aa 100644 --- a/src/components/PlaidLink/index.js +++ b/src/components/PlaidLink/index.tsx @@ -1,35 +1,33 @@ import {useCallback, useEffect, useState} from 'react'; -import {usePlaidLink} from 'react-plaid-link'; +import {PlaidLinkOnSuccessMetadata, usePlaidLink} from 'react-plaid-link'; import Log from '@libs/Log'; -import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; +import PlaidLinkProps from './types'; -function PlaidLink(props) { +function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () => {}, onEvent, receivedRedirectURI}: PlaidLinkProps) { const [isPlaidLoaded, setIsPlaidLoaded] = useState(false); - const onSuccess = props.onSuccess; - const onError = props.onError; const successCallback = useCallback( - (publicToken, metadata) => { + (publicToken: string, metadata: PlaidLinkOnSuccessMetadata) => { onSuccess({publicToken, metadata}); }, [onSuccess], ); const {open, ready, error} = usePlaidLink({ - token: props.token, + token, onSuccess: successCallback, onExit: (exitError, metadata) => { Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); - props.onExit(); + onExit(); }, onEvent: (event, metadata) => { Log.info('[PlaidLink] Event: ', false, {event, metadata}); - props.onEvent(event, metadata); + onEvent(event, metadata); }, onLoad: () => setIsPlaidLoaded(true), // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform - receivedRedirectUri: props.receivedRedirectURI, + receivedRedirectUri: receivedRedirectURI, }); useEffect(() => { @@ -52,7 +50,5 @@ function PlaidLink(props) { return null; } -PlaidLink.propTypes = plaidLinkPropTypes; -PlaidLink.defaultProps = plaidLinkDefaultProps; PlaidLink.displayName = 'PlaidLink'; export default PlaidLink; diff --git a/src/components/PlaidLink/nativeModule/index.android.js b/src/components/PlaidLink/nativeModule/index.android.js deleted file mode 100644 index d4280feddb8e..000000000000 --- a/src/components/PlaidLink/nativeModule/index.android.js +++ /dev/null @@ -1,3 +0,0 @@ -import {NativeModules} from 'react-native'; - -export default NativeModules.PlaidAndroid; diff --git a/src/components/PlaidLink/nativeModule/index.ios.js b/src/components/PlaidLink/nativeModule/index.ios.js deleted file mode 100644 index 78d4315eac2d..000000000000 --- a/src/components/PlaidLink/nativeModule/index.ios.js +++ /dev/null @@ -1,3 +0,0 @@ -import {NativeModules} from 'react-native'; - -export default NativeModules.RNLinksdk; diff --git a/src/components/PlaidLink/plaidLinkPropTypes.js b/src/components/PlaidLink/types.ts similarity index 50% rename from src/components/PlaidLink/plaidLinkPropTypes.js rename to src/components/PlaidLink/types.ts index 6d647d26f17e..1034eb935f74 100644 --- a/src/components/PlaidLink/plaidLinkPropTypes.js +++ b/src/components/PlaidLink/types.ts @@ -1,31 +1,25 @@ -import PropTypes from 'prop-types'; +import {LinkEventMetadata, LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; +import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; -const plaidLinkPropTypes = { +type PlaidLinkProps = { // Plaid Link SDK public token used to initialize the Plaid SDK - token: PropTypes.string.isRequired, + token: string; // Callback to execute once the user taps continue after successfully entering their account information - onSuccess: PropTypes.func, + onSuccess?: (args: {publicToken: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; // Callback to execute when there is an error event emitted by the Plaid SDK - onError: PropTypes.func, + onError?: (error: ErrorEvent | null) => void; // Callback to execute when the user leaves the Plaid widget flow without entering any information - onExit: PropTypes.func, + onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent: PropTypes.func, + onEvent: (eventName: string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform - receivedRedirectURI: PropTypes.string, + receivedRedirectURI?: string; }; -const plaidLinkDefaultProps = { - onSuccess: () => {}, - onError: () => {}, - onExit: () => {}, - receivedRedirectURI: null, -}; - -export {plaidLinkPropTypes, plaidLinkDefaultProps}; +export default PlaidLinkProps;