diff --git a/packages/shared/src/UI/components/ERC20TokenList/ERC20TokenListItem.tsx b/packages/shared/src/UI/components/ERC20TokenList/ERC20TokenListItem.tsx index aa2a399871f9..77373a1f80e2 100644 --- a/packages/shared/src/UI/components/ERC20TokenList/ERC20TokenListItem.tsx +++ b/packages/shared/src/UI/components/ERC20TokenList/ERC20TokenListItem.tsx @@ -142,6 +142,7 @@ export const getERC20TokenListItem = return ( { targetChainId?: ChainId @@ -64,7 +65,7 @@ export const ERC20TokenList = memo((props) => { } = props const { ERC20 } = useTokenListConstants(chainId) - const { value: erc20TokensDetailed = [], loading: erc20TokensDetailedLoading } = + const { value: erc20TokensDetailed = EMPTY_LIST, loading: erc20TokensDetailedLoading } = useERC20TokensDetailedFromTokenLists( ERC20, keyword, @@ -87,8 +88,9 @@ export const ERC20TokenList = memo((props) => { (!excludeTokens.length || !excludeTokens.some(currySameAddress(token.address))), ) - const renderTokens = uniqBy([...tokens, ...filteredTokens, ...(searchedToken ? [searchedToken] : [])], (x) => - x.address.toLowerCase(), + const renderTokens = uniqBy( + [...tokens, ...filteredTokens, ...(searchedToken ? [searchedToken] : EMPTY_LIST)], + (x) => x.address.toLowerCase(), ) const { @@ -101,17 +103,24 @@ export const ERC20TokenList = memo((props) => { chainId, ) - const renderAssets = - !account || !!assetsError || assetsLoading || searchedTokenLoading - ? [...renderTokens] - .sort(makeSortTokenFn(chainId, { isMaskBoost: true })) - .map((token) => ({ token: token, balance: null })) + const renderAssets = useMemo(() => { + return assetsLoading + ? EMPTY_LIST : keyword ? assets : [...assets].sort(makeSortAssertFn(chainId, { isMaskBoost: true })) + }, [ + chainId, + keyword, + assetsLoading, + assets + .map((x) => x.token.address) + .sort() + .join(), + ]) const getPlaceHolder = () => { - if (erc20TokensDetailedLoading) + if (erc20TokensDetailedLoading || assetsLoading) return if (searchedTokenLoading) return @@ -130,7 +139,7 @@ export const ERC20TokenList = memo((props) => { disableSearch={!!props.disableSearch} onSearch={setKeyword} data={renderAssets as Asset[]} - searchKey={['token.address', 'token.symbol', 'token.name']} + searchKey={SEARCH_KEYS} itemRender={getERC20TokenListItem( trustedERC20Tokens, searchedToken ? [searchedToken] : [], diff --git a/packages/shared/src/locales/en-US.json b/packages/shared/src/locales/en-US.json index 134f72c9fc51..c0aca43099c6 100644 --- a/packages/shared/src/locales/en-US.json +++ b/packages/shared/src/locales/en-US.json @@ -4,7 +4,7 @@ "balance": "Balance", "select_token": "Select a Token", "erc20_token_list_placeholder": "Token name or contract address", - "erc20_token_list_loading": "Loading token lists..", + "erc20_token_list_loading": "Loading token lists...", "erc20_search_token_loading": "Loading token...", "erc20_search_not_token_found": "No results or contract address does not meet the query criteria.", "address_viewer_binding_rules_title": "The NFT gallary will show NFTs as below rules:", diff --git a/packages/theme/src/Components/SearchableList/SearchableList.tsx b/packages/theme/src/Components/SearchableList/SearchableList.tsx index 4bc8abaa134b..33906a773398 100644 --- a/packages/theme/src/Components/SearchableList/SearchableList.tsx +++ b/packages/theme/src/Components/SearchableList/SearchableList.tsx @@ -48,7 +48,7 @@ export interface MaskSearchableListProps { * /> * ) */ -export function SearchableList({ +export function SearchableList({ itemKey, data, placeholder, @@ -72,7 +72,7 @@ export function SearchableList({ shouldSort: true, threshold: 0.45, minMatchCharLength: 1, - keys: searchKey ?? Object.keys(data.length > 0 ? data[0] : ([] as any)), + keys: searchKey ?? data.length > 0 ? Object.keys(data[0]) : [], }), [data, searchKey], ) diff --git a/packages/web3-shared/evm/hooks/useERC20TokensDetailedFromTokenLists.ts b/packages/web3-shared/evm/hooks/useERC20TokensDetailedFromTokenLists.ts index f39867966928..e516049e2d39 100644 --- a/packages/web3-shared/evm/hooks/useERC20TokensDetailedFromTokenLists.ts +++ b/packages/web3-shared/evm/hooks/useERC20TokensDetailedFromTokenLists.ts @@ -7,18 +7,19 @@ import { useWeb3Context } from '../context' import { useChainId } from './useChainId' import { currySameAddress } from '../utils' import type { ERC20TokenDetailed, NativeTokenDetailed, ChainId } from '../types' +import { EMPTY_LIST } from '@masknet/shared-base' export function useERC20TokensDetailedFromTokenLists( lists?: string[], keyword = '', - additionalTokens: (ERC20TokenDetailed | NativeTokenDetailed)[] = [], + additionalTokens: (ERC20TokenDetailed | NativeTokenDetailed)[] = EMPTY_LIST, targetChainId?: ChainId, ): AsyncStateRetry<(ERC20TokenDetailed | NativeTokenDetailed)[]> { // #region fetch token lists const currentChainId = useChainId() const chainId = targetChainId ?? currentChainId const { fetchERC20TokensFromTokenLists } = useWeb3Context() - const { value: tokensFromList = [], ...asyncResult } = useAsyncRetry( + const { value: tokensFromList = EMPTY_LIST, ...asyncResult } = useAsyncRetry( async () => (!lists || lists.length === 0 ? [] : fetchERC20TokensFromTokenLists(lists, chainId)), [chainId, lists?.sort().join()], ) @@ -35,7 +36,7 @@ export function useERC20TokensDetailedFromTokenLists( { name: 'symbol', weight: 1 }, ], }), - [tokensFromList, additionalTokens], + [tokensFromList, additionalTokens.map((x) => x.address).join()], ) // #endregion @@ -48,7 +49,7 @@ export function useERC20TokensDetailedFromTokenLists( ...(EthereumAddress.isValid(keyword) ? allToken.filter(currySameAddress(keyword)) : []), ...fuse.search(keyword).map((x) => x.item), ] - }, [keyword, fuse, tokensFromList, additionalTokens]) + }, [keyword, fuse, tokensFromList, additionalTokens.map((x) => x.address).join()]) // #endregion if (!asyncResult.error)