From 5b6e0876cbd205061865ebd1d81d13af439c598e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Przemys=C5=82aw=20Sosna?=
<43684335+SosenWiosen@users.noreply.github.com>
Date: Thu, 10 Aug 2023 15:24:40 +0200
Subject: [PATCH 1/3] setup most of the logic
---
src/components/AddPlaidBankAccount.js | 244 +++++++++++++-------------
1 file changed, 122 insertions(+), 122 deletions(-)
diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js
index ff97c9be24a6..b2c56d7e24e5 100644
--- a/src/components/AddPlaidBankAccount.js
+++ b/src/components/AddPlaidBankAccount.js
@@ -1,5 +1,5 @@
import _ from 'underscore';
-import React from 'react';
+import React, {useEffect, useState} from 'react';
import {ActivityIndicator, View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
@@ -68,164 +68,164 @@ const defaultProps = {
bankAccountID: 0,
};
-class AddPlaidBankAccount extends React.Component {
- constructor(props) {
- super(props);
-
- this.getPlaidLinkToken = this.getPlaidLinkToken.bind(this);
- this.subscribedKeyboardShortcuts = [];
- }
-
- componentDidMount() {
- this.subscribeToNavigationShortcuts();
-
- // If we're coming from Plaid OAuth flow then we need to reuse the existing plaidLinkToken
- if (this.isAuthenticatedWithPlaid()) {
- return;
- }
-
- BankAccounts.openPlaidBankLogin(this.props.allowDebit, this.props.bankAccountID);
- }
-
- componentDidUpdate(prevProps) {
- if (!prevProps.network.isOffline || this.props.network.isOffline || this.isAuthenticatedWithPlaid()) {
- return;
- }
-
- // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid
- BankAccounts.openPlaidBankLogin(this.props.allowDebit, this.props.bankAccountID);
- }
-
- componentWillUnmount() {
- this.unsubscribeToNavigationShortcuts();
- }
+function AddPlaidBankAccount({
+ plaidData,
+ selectedPlaidAccountID,
+ plaidLinkToken,
+ onExitPlaid,
+ onSelect,
+ text,
+ receivedRedirectURI,
+ plaidLinkOAuthToken,
+ bankAccountID,
+ allowDebit,
+ translate,
+ network,
+}) {
+ const [subscribedKeyboardShortcuts, setSubscribedKeyboardShortcuts] = useState([]);
/**
* @returns {String}
*/
- getPlaidLinkToken() {
- if (this.props.plaidLinkToken) {
- return this.props.plaidLinkToken;
+ const getPlaidLinkToken = () => {
+ if (plaidLinkToken) {
+ return plaidLinkToken;
}
- if (this.props.receivedRedirectURI && this.props.plaidLinkOAuthToken) {
- return this.props.plaidLinkOAuthToken;
+ if (receivedRedirectURI && plaidLinkOAuthToken) {
+ return plaidLinkOAuthToken;
}
- }
+ };
/**
* @returns {Boolean}
*/
- isAuthenticatedWithPlaid() {
- return (
- (this.props.receivedRedirectURI && this.props.plaidLinkOAuthToken) ||
- !_.isEmpty(lodashGet(this.props.plaidData, 'bankAccounts')) ||
- !_.isEmpty(lodashGet(this.props.plaidData, 'errors'))
- );
- }
+ const isAuthenticatedWithPlaid = () => (receivedRedirectURI && plaidLinkOAuthToken) || !_.isEmpty(lodashGet(plaidData, 'bankAccounts')) || !_.isEmpty(lodashGet(plaidData, 'errors'));
/**
* Blocks the keyboard shortcuts that can navigate
*/
- subscribeToNavigationShortcuts() {
+ const subscribeToNavigationShortcuts = () => {
// find and block the shortcuts
const shortcutsToBlock = _.filter(CONST.KEYBOARD_SHORTCUTS, (x) => x.type === CONST.KEYBOARD_SHORTCUTS_TYPES.NAVIGATION_SHORTCUT);
- this.subscribedKeyboardShortcuts = _.map(shortcutsToBlock, (shortcut) =>
- KeyboardShortcut.subscribe(
- shortcut.shortcutKey,
- () => {}, // do nothing
- shortcut.descriptionKey,
- shortcut.modifiers,
- false,
- () => lodashGet(this.props.plaidData, 'bankAccounts', []).length > 0, // start bubbling when there are bank accounts
+ setSubscribedKeyboardShortcuts(
+ _.map(shortcutsToBlock, (shortcut) =>
+ KeyboardShortcut.subscribe(
+ shortcut.shortcutKey,
+ () => {}, // do nothing
+ shortcut.descriptionKey,
+ shortcut.modifiers,
+ false,
+ () => lodashGet(plaidData, 'bankAccounts', []).length > 0, // start bubbling when there are bank accounts
+ ),
),
);
- }
+ };
/**
* Unblocks the keyboard shortcuts that can navigate
*/
- unsubscribeToNavigationShortcuts() {
- _.each(this.subscribedKeyboardShortcuts, (unsubscribe) => unsubscribe());
- this.subscribedKeyboardShortcuts = [];
- }
+ const unsubscribeToNavigationShortcuts = () => {
+ _.each(subscribedKeyboardShortcuts, (unsubscribe) => unsubscribe());
+ setSubscribedKeyboardShortcuts([]);
+ };
- render() {
- const plaidBankAccounts = lodashGet(this.props.plaidData, 'bankAccounts') || [];
- const token = this.getPlaidLinkToken();
- const options = _.map(plaidBankAccounts, (account) => ({
- value: account.plaidAccountID,
- label: `${account.addressName} ${account.mask}`,
- }));
- const {icon, iconSize} = getBankIcon();
- const plaidErrors = lodashGet(this.props.plaidData, 'errors');
- const plaidDataErrorMessage = !_.isEmpty(plaidErrors) ? _.chain(plaidErrors).values().first().value() : '';
- const bankName = lodashGet(this.props.plaidData, 'bankName');
-
- // Plaid Link view
- if (!plaidBankAccounts.length) {
- return (
-
- {lodashGet(this.props.plaidData, 'isLoading') && (
-
-
-
- )}
- {Boolean(plaidDataErrorMessage) && {plaidDataErrorMessage}}
- {Boolean(token) && !bankName && (
- {
- Log.info('[PlaidLink] Success!');
- BankAccounts.openPlaidBankAccountSelector(publicToken, metadata.institution.name, this.props.allowDebit, this.props.bankAccountID);
- }}
- onError={(error) => {
- Log.hmmm('[PlaidLink] Error: ', error.message);
- }}
- // User prematurely exited the Plaid flow
- // eslint-disable-next-line react/jsx-props-no-multi-spaces
- onExit={this.props.onExitPlaid}
- receivedRedirectURI={this.props.receivedRedirectURI}
- />
- )}
-
- );
+ useEffect(() => {
+ subscribeToNavigationShortcuts();
+
+ // If we're coming from Plaid OAuth flow then we need to reuse the existing plaidLinkToken
+ if (isAuthenticatedWithPlaid()) {
+ return;
}
- // Plaid bank accounts view
+ BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
+ return unsubscribeToNavigationShortcuts;
+ });
+
+ useEffect(() => {
+ if (!prevProps.network.isOffline || network.isOffline || isAuthenticatedWithPlaid()) {
+ return;
+ }
+
+ // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid
+ BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
+ });
+
+ const plaidBankAccounts = lodashGet(plaidData, 'bankAccounts') || [];
+ const token = getPlaidLinkToken();
+ const options = _.map(plaidBankAccounts, (account) => ({
+ value: account.plaidAccountID,
+ label: `${account.addressName} ${account.mask}`,
+ }));
+ const {icon, iconSize} = getBankIcon();
+ const plaidErrors = lodashGet(plaidData, 'errors');
+ const plaidDataErrorMessage = !_.isEmpty(plaidErrors) ? _.chain(plaidErrors).values().first().value() : '';
+ const bankName = lodashGet(plaidData, 'bankName');
+
+ // Plaid Link view
+ if (!plaidBankAccounts.length) {
return (
- {!_.isEmpty(this.props.text) && {this.props.text}}
-
-
- {bankName}
-
-
-
+
+
+ )}
+ {Boolean(plaidDataErrorMessage) && {plaidDataErrorMessage}}
+ {Boolean(token) && !bankName && (
+ {
+ Log.info('[PlaidLink] Success!');
+ BankAccounts.openPlaidBankAccountSelector(publicToken, metadata.institution.name, allowDebit, bankAccountID);
}}
- value={this.props.selectedPlaidAccountID}
+ onError={(error) => {
+ Log.hmmm('[PlaidLink] Error: ', error.message);
+ }}
+ // User prematurely exited the Plaid flow
+ // eslint-disable-next-line react/jsx-props-no-multi-spaces
+ onExit={onExitPlaid}
+ receivedRedirectURI={receivedRedirectURI}
/>
-
+ )}
);
}
+
+ // Plaid bank accounts view
+ return (
+
+ {!_.isEmpty(text) && {text}}
+
+
+ {bankName}
+
+
+
+
+
+ );
}
AddPlaidBankAccount.propTypes = propTypes;
AddPlaidBankAccount.defaultProps = defaultProps;
+AddPlaidBankAccount.displayName = 'AddPlaidBankAccount';
export default compose(
withLocalize,
From d3ea842a9271329ed61db3ecc7bf107a70d228b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Przemys=C5=82aw=20Sosna?=
<43684335+SosenWiosen@users.noreply.github.com>
Date: Fri, 11 Aug 2023 11:17:06 +0200
Subject: [PATCH 2/3] finished migrated logic
---
src/components/AddPlaidBankAccount.js | 93 ++++++++++++---------------
1 file changed, 40 insertions(+), 53 deletions(-)
diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js
index b2c56d7e24e5..f95f670165e4 100644
--- a/src/components/AddPlaidBankAccount.js
+++ b/src/components/AddPlaidBankAccount.js
@@ -1,5 +1,5 @@
import _ from 'underscore';
-import React, {useEffect, useState} from 'react';
+import React, {useEffect, useRef, useCallback} from 'react';
import {ActivityIndicator, View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
@@ -10,17 +10,16 @@ import * as BankAccounts from '../libs/actions/BankAccounts';
import ONYXKEYS from '../ONYXKEYS';
import styles from '../styles/styles';
import themeColors from '../styles/themes/default';
-import compose from '../libs/compose';
-import withLocalize, {withLocalizePropTypes} from './withLocalize';
import Picker from './Picker';
import {plaidDataPropTypes} from '../pages/ReimbursementAccount/plaidDataPropTypes';
import Text from './Text';
import getBankIcon from './Icon/BankIcons';
import Icon from './Icon';
import FullPageOfflineBlockingView from './BlockingViews/FullPageOfflineBlockingView';
-import {withNetwork} from './OnyxProvider';
import CONST from '../CONST';
import KeyboardShortcut from '../libs/KeyboardShortcut';
+import useLocalize from '../hooks/useLocalize';
+import useNetwork from '../hooks/useNetwork';
const propTypes = {
/** Contains plaid data */
@@ -52,8 +51,6 @@ const propTypes = {
/** Are we adding a withdrawal account? */
allowDebit: PropTypes.bool,
-
- ...withLocalizePropTypes,
};
const defaultProps = {
@@ -68,21 +65,12 @@ const defaultProps = {
bankAccountID: 0,
};
-function AddPlaidBankAccount({
- plaidData,
- selectedPlaidAccountID,
- plaidLinkToken,
- onExitPlaid,
- onSelect,
- text,
- receivedRedirectURI,
- plaidLinkOAuthToken,
- bankAccountID,
- allowDebit,
- translate,
- network,
-}) {
- const [subscribedKeyboardShortcuts, setSubscribedKeyboardShortcuts] = useState([]);
+function AddPlaidBankAccount({plaidData, selectedPlaidAccountID, plaidLinkToken, onExitPlaid, onSelect, text, receivedRedirectURI, plaidLinkOAuthToken, bankAccountID, allowDebit}) {
+ const subscribedKeyboardShortcuts = useRef([]);
+ const previousNetworkState = useRef();
+
+ const {translate} = useLocalize();
+ const {isOffline} = useNetwork();
/**
* @returns {String}
@@ -99,8 +87,12 @@ function AddPlaidBankAccount({
/**
* @returns {Boolean}
+ * I'm using useCallback so the useEffect which uses this function doesn't run on every render.
*/
- const isAuthenticatedWithPlaid = () => (receivedRedirectURI && plaidLinkOAuthToken) || !_.isEmpty(lodashGet(plaidData, 'bankAccounts')) || !_.isEmpty(lodashGet(plaidData, 'errors'));
+ const isAuthenticatedWithPlaid = useCallback(
+ () => (receivedRedirectURI && plaidLinkOAuthToken) || !_.isEmpty(lodashGet(plaidData, 'bankAccounts')) || !_.isEmpty(lodashGet(plaidData, 'errors')),
+ [plaidData, plaidLinkOAuthToken, receivedRedirectURI],
+ );
/**
* Blocks the keyboard shortcuts that can navigate
@@ -108,16 +100,14 @@ function AddPlaidBankAccount({
const subscribeToNavigationShortcuts = () => {
// find and block the shortcuts
const shortcutsToBlock = _.filter(CONST.KEYBOARD_SHORTCUTS, (x) => x.type === CONST.KEYBOARD_SHORTCUTS_TYPES.NAVIGATION_SHORTCUT);
- setSubscribedKeyboardShortcuts(
- _.map(shortcutsToBlock, (shortcut) =>
- KeyboardShortcut.subscribe(
- shortcut.shortcutKey,
- () => {}, // do nothing
- shortcut.descriptionKey,
- shortcut.modifiers,
- false,
- () => lodashGet(plaidData, 'bankAccounts', []).length > 0, // start bubbling when there are bank accounts
- ),
+ subscribedKeyboardShortcuts.current = _.map(shortcutsToBlock, (shortcut) =>
+ KeyboardShortcut.subscribe(
+ shortcut.shortcutKey,
+ () => {}, // do nothing
+ shortcut.descriptionKey,
+ shortcut.modifiers,
+ false,
+ () => lodashGet(plaidData, 'bankAccounts', []).length > 0, // start bubbling when there are bank accounts
),
);
};
@@ -127,29 +117,30 @@ function AddPlaidBankAccount({
*/
const unsubscribeToNavigationShortcuts = () => {
_.each(subscribedKeyboardShortcuts, (unsubscribe) => unsubscribe());
- setSubscribedKeyboardShortcuts([]);
+ subscribedKeyboardShortcuts.current = [];
};
useEffect(() => {
subscribeToNavigationShortcuts();
// If we're coming from Plaid OAuth flow then we need to reuse the existing plaidLinkToken
- if (isAuthenticatedWithPlaid()) {
- return;
+ if (!isAuthenticatedWithPlaid()) {
+ BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
}
- BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
return unsubscribeToNavigationShortcuts;
- });
+ // disabling this rule, as we want this to run only on the first render
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
useEffect(() => {
- if (!prevProps.network.isOffline || network.isOffline || isAuthenticatedWithPlaid()) {
- return;
+ // previousNetworkState.current also makes sure that this doesn't run on the first render, as null is falsy.
+ if (previousNetworkState.current && !isOffline && !isAuthenticatedWithPlaid()) {
+ // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid
+ BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
}
-
- // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid
- BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
- });
+ previousNetworkState.current = isOffline;
+ }, [allowDebit, bankAccountID, isAuthenticatedWithPlaid, isOffline]);
const plaidBankAccounts = lodashGet(plaidData, 'bankAccounts') || [];
const token = getPlaidLinkToken();
@@ -227,13 +218,9 @@ AddPlaidBankAccount.propTypes = propTypes;
AddPlaidBankAccount.defaultProps = defaultProps;
AddPlaidBankAccount.displayName = 'AddPlaidBankAccount';
-export default compose(
- withLocalize,
- withNetwork(),
- withOnyx({
- plaidLinkToken: {
- key: ONYXKEYS.PLAID_LINK_TOKEN,
- initWithStoredValues: false,
- },
- }),
-)(AddPlaidBankAccount);
+export default withOnyx({
+ plaidLinkToken: {
+ key: ONYXKEYS.PLAID_LINK_TOKEN,
+ initWithStoredValues: false,
+ },
+})(AddPlaidBankAccount);
From 3d4897959189895c91c7751ebece76213617b290 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Przemys=C5=82aw=20Sosna?=
<43684335+SosenWiosen@users.noreply.github.com>
Date: Fri, 11 Aug 2023 13:44:26 +0200
Subject: [PATCH 3/3] fix small errors
---
src/components/AddPlaidBankAccount.js | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js
index f95f670165e4..d50fad0bd2f0 100644
--- a/src/components/AddPlaidBankAccount.js
+++ b/src/components/AddPlaidBankAccount.js
@@ -116,7 +116,7 @@ function AddPlaidBankAccount({plaidData, selectedPlaidAccountID, plaidLinkToken,
* Unblocks the keyboard shortcuts that can navigate
*/
const unsubscribeToNavigationShortcuts = () => {
- _.each(subscribedKeyboardShortcuts, (unsubscribe) => unsubscribe());
+ _.each(subscribedKeyboardShortcuts.current, (unsubscribe) => unsubscribe());
subscribedKeyboardShortcuts.current = [];
};
@@ -124,19 +124,20 @@ function AddPlaidBankAccount({plaidData, selectedPlaidAccountID, plaidLinkToken,
subscribeToNavigationShortcuts();
// If we're coming from Plaid OAuth flow then we need to reuse the existing plaidLinkToken
- if (!isAuthenticatedWithPlaid()) {
- BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
+ if (isAuthenticatedWithPlaid()) {
+ return unsubscribeToNavigationShortcuts;
}
-
+ BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
return unsubscribeToNavigationShortcuts;
+
// disabling this rule, as we want this to run only on the first render
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
- // previousNetworkState.current also makes sure that this doesn't run on the first render, as null is falsy.
+ // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid
+ // previousNetworkState.current also makes sure that this doesn't run on the first render.
if (previousNetworkState.current && !isOffline && !isAuthenticatedWithPlaid()) {
- // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid
BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID);
}
previousNetworkState.current = isOffline;