[NoQA] Fix Virtualised List Error#49487
Conversation
|
Let's wrap it by View Component. This is draft implementation. YOu can apply more style to View to display the correct UI |
@DylanDylann Your solution doesn't work well with scrolling or when we have several bank accounts, take a look: Screen.Recording.2024-09-20.at.11.29.13.mov |
|
@DylanDylann @allgandalf One easy way to solve this particular case is to use the <SelectionList
sections={[{data}]}
ListItem={RadioListItem}
onSelectRow={(value) => {
const accountType = value?.bankAccount?.accountType;
const accountData = value?.bankAccount?.accountData;
selectAccountAndNavigateBack(accountType, accountData);
}}
shouldSingleExecuteRowSelect
shouldUpdateFocusedIndex
initiallyFocusedOptionKey={walletTransfer?.selectedAccountID?.toString()}
listFooterContent={
<MenuItem
onPress={navigateToAddPaymentMethodPage}
title={
walletTransfer?.filterPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT
? translate('paymentMethodList.addNewBankAccount')
: translate('paymentMethodList.addNewDebitCard')
}
icon={Expensicons.Plus}
/>
}
/>Screen.Recording.2024-09-20.at.11.32.04.movI tested on iOS Native, Safari MWeb and Chrome, seems to work well. We should test on Android too. The only drawback of this approach is that by supplying the |
|
@fabioh8010 Great, It looks fine |
This would really be an edge case, and in general no single user would have 500+ bank accounts, so i guess this solution would work good, I will also apply this in |
|
Here's the full diff in case you want to test with a lot of bank accounts: diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx
index 0bbcf957c31..e3deeeeb711 100644
--- a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx
+++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx
@@ -8,9 +8,9 @@ import getBankIcon from '@components/Icon/BankIcons';
import * as Expensicons from '@components/Icon/Expensicons';
import MenuItem from '@components/MenuItem';
import ScreenWrapper from '@components/ScreenWrapper';
-import ScrollView from '@components/ScrollView';
import SelectionList from '@components/SelectionList';
import RadioListItem from '@components/SelectionList/RadioListItem';
+import type {ListItem} from '@components/SelectionList/types';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import {getLastFourDigits} from '@libs/BankAccountUtils';
@@ -20,10 +20,15 @@ import * as PaymentMethods from '@userActions/PaymentMethods';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
-import type {AccountData} from '@src/types/onyx';
+import type {AccountData, BankAccount} from '@src/types/onyx';
import type {BankName} from '@src/types/onyx/Bank';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
+type AccountListItem = ListItem & {
+ value?: number;
+ bankAccount: BankAccount;
+};
+
function ChooseTransferAccountPage() {
const [walletTransfer, walletTransferResult] = useOnyx(ONYXKEYS.WALLET_TRANSFER);
@@ -54,7 +59,7 @@ function ChooseTransferAccountPage() {
const [bankAccountsList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
const selectedAccountID = walletTransfer?.selectedAccountID;
const data = useMemo(() => {
- const options = Object.values(bankAccountsList ?? {}).map((bankAccount) => {
+ const options = Object.values(bankAccountsList ?? {}).map((bankAccount): AccountListItem => {
const bankName = (bankAccount.accountData?.additionalData?.bankName ?? '') as BankName;
const bankAccountNumber = bankAccount.accountData?.accountNumber ?? '';
const bankAccountID = bankAccount.accountData?.bankAccountID ?? bankAccount.methodID;
@@ -78,7 +83,31 @@ function ChooseTransferAccountPage() {
bankAccount,
};
});
- return options;
+
+ const testOptions = Array.from({length: 20}).map((v, i): AccountListItem => {
+ const {icon, iconSize, iconStyles} = getBankIcon({styles});
+
+ return {
+ value: i,
+ text: `Bank ${i}`,
+ leftElement: (
+ <View style={[styles.flexRow, styles.alignItemsCenter, styles.mr3]}>
+ <Icon
+ src={icon}
+ width={iconSize}
+ height={iconSize}
+ additionalStyles={iconStyles}
+ />
+ </View>
+ ),
+ alternateText: `Bank ${i} text`,
+ keyForList: i.toString(),
+ isSelected: false,
+ bankAccount: {},
+ };
+ });
+
+ return options.concat(testOptions);
}, [bankAccountsList, selectedAccountID, styles, translate]);
if (isLoadingOnyxValue(walletTransferResult)) {
@@ -91,29 +120,29 @@ function ChooseTransferAccountPage() {
title={translate('chooseTransferAccountPage.chooseAccount')}
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE)}
/>
- <ScrollView>
- <SelectionList
- sections={[{data}]}
- ListItem={RadioListItem}
- onSelectRow={(value) => {
- const accountType = value?.bankAccount?.accountType;
- const accountData = value?.bankAccount?.accountData;
- selectAccountAndNavigateBack(accountType, accountData);
- }}
- shouldSingleExecuteRowSelect
- shouldUpdateFocusedIndex
- initiallyFocusedOptionKey={walletTransfer?.selectedAccountID?.toString()}
- />
- <MenuItem
- onPress={navigateToAddPaymentMethodPage}
- title={
- walletTransfer?.filterPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT
- ? translate('paymentMethodList.addNewBankAccount')
- : translate('paymentMethodList.addNewDebitCard')
- }
- icon={Expensicons.Plus}
- />
- </ScrollView>
+ <SelectionList
+ sections={[{data}]}
+ ListItem={RadioListItem}
+ onSelectRow={(value) => {
+ const accountType = value?.bankAccount?.accountType;
+ const accountData = value?.bankAccount?.accountData;
+ selectAccountAndNavigateBack(accountType, accountData);
+ }}
+ shouldSingleExecuteRowSelect
+ shouldUpdateFocusedIndex
+ initiallyFocusedOptionKey={walletTransfer?.selectedAccountID?.toString()}
+ listFooterContent={
+ <MenuItem
+ onPress={navigateToAddPaymentMethodPage}
+ title={
+ walletTransfer?.filterPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT
+ ? translate('paymentMethodList.addNewBankAccount')
+ : translate('paymentMethodList.addNewDebitCard')
+ }
+ icon={Expensicons.Plus}
+ />
+ }
+ />
</ScreenWrapper>
);
}
|
|
@DylanDylann Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Reviewer Checklist
Screenshots/VideosAndroid: NativeScreen.Recording.2024-09-20.at.20.15.05.movAndroid: mWeb ChromeScreen.Recording.2024-09-20.at.20.14.21.moviOS: NativeScreen.Recording.2024-09-20.at.20.15.29.moviOS: mWeb SafariScreen.Recording.2024-09-20.at.20.13.05.movMacOS: Chrome / SafariScreen.Recording.2024-09-20.at.20.11.46.movMacOS: DesktopScreen.Recording.2024-09-20.at.20.13.36.mov |
|
|
||
| This ensures optimal performance and avoids layout issues. | ||
|
|
||
|
|
Co-authored-by: Fábio Henriques <fabio.lacerda@outlook.com>
Co-authored-by: Fábio Henriques <fabio.lacerda@outlook.com>
Co-authored-by: Fábio Henriques <fabio.lacerda@outlook.com>
|
@fabioh8010 the following is the latest view after the suggestions, does that look fine now?
|
|
LGTM! |
mountiny
left a comment
There was a problem hiding this comment.
Thank you, one NAB so going to merge
|
|
||
| ### Problem | ||
|
|
||
| When using `SelectionList` alongside other components (e.g., `Text`, `Button`), wrapping them inside a `ScrollView` can lead to alignment and performance issues. Additionally, using `ScrollView` with nested `FlatList` or `SectionList` causes the error: |
There was a problem hiding this comment.
| When using `SelectionList` alongside other components (e.g., `Text`, `Button`), wrapping them inside a `ScrollView` can lead to alignment and performance issues. Additionally, using `ScrollView` with nested `FlatList` or `SectionList` causes the error: | |
| When using `SelectionList` alongside other components (e.g., `Text`, `Button`), wrapping them inside a `ScrollView` can lead to alignment and performance issues. Additionally, using `ScrollView` with nested `FlatList` or `SectionList` causes this error: |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/mountiny in version: 9.0.40-0 🚀
|
|
🚀 Deployed to production by https://github.com/AndrewGable in version: 9.0.40-6 🚀
|


Details
We cannot use
ScrollViewwithSelectionListbecause it isanti-patternand will lead to performance issues and bugs.With this PR, we are removing the usage of
ScrollViewand adding the extra components as eitherlistHeaderContentorlistFooterContentFixed Issues
$ #48974
PROPOSAL:
Tests
DevenvironmentPREREQUISITES: all betas or workspace feed beta enables
Verify that we do not get the error:
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.Comment this line of code to shouldShow={false}.
Have 2 bank accounts set up on wallet page
Go to settings/wallet/choose-transfer-account
Verify that we do not get the error:
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.Offline tests
N/A
QA Steps
N/A
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)myBool && <MyComponent />.src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Screen.Recording.2024-09-20.at.5.51.23.PM.mov
MacOS: Desktop