-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[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. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs looks like the below @mountiny
Co-authored-by: Fábio Henriques <[email protected]>
Co-authored-by: Fábio Henriques <[email protected]>
Co-authored-by: Fábio Henriques <[email protected]>
@fabioh8010 the following is the latest view after the suggestions, does that look fine now? |
LGTM! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
ScrollView
withSelectionList
because it isanti-pattern
and will lead to performance issues and bugs.With this PR, we are removing the usage of
ScrollView
and adding the extra components as eitherlistHeaderContent
orlistFooterContent
Fixed Issues
$ #48974
PROPOSAL:
Tests
Dev
environmentPREREQUISITES: 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 Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.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