useLoadingDelay for large lists (#3310)
* useLoadingDelay for large lists * Accounts with isLoading * sortedAddresses afecting check
This commit is contained in:
parent
3b4752106c
commit
6aefdd9178
@ -11,7 +11,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
import { getLedger, isLedger } from '@polkadot/react-api';
|
||||
import { useApi, useAccounts, useCall, useFavorites, useIpfs, useToggle } from '@polkadot/react-hooks';
|
||||
import { useApi, useAccounts, useCall, useFavorites, useIpfs, useLoadingDelay, useToggle } from '@polkadot/react-hooks';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { Button, Input, Table } from '@polkadot/react-components';
|
||||
import { BN_ZERO } from '@polkadot/util';
|
||||
@ -70,10 +70,11 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
|
||||
const [favorites, toggleFavorite] = useFavorites(STORE_FAVS);
|
||||
const [{ balanceTotal }, setBalances] = useState<Balances>({ accounts: {} });
|
||||
const [filterOn, setFilter] = useState<string>('');
|
||||
const [sortedAccountsWithDelegation, setSortedAccountsWithDelegation] = useState<SortedAccount[]>([]);
|
||||
const [sortedAccountsWithDelegation, setSortedAccountsWithDelegation] = useState<SortedAccount[] | undefined>();
|
||||
const [{ sortedAccounts, sortedAddresses }, setSorted] = useState<Sorted>({ sortedAccounts: [], sortedAddresses: [] });
|
||||
const delegations = useCall<Voting[]>(api.query.democracy?.votingOf?.multi, [sortedAddresses]);
|
||||
const proxies = useCall<[[AccountId, ProxyType][], BN][]>(api.query.proxy?.proxies.multi, [sortedAddresses]);
|
||||
const isLoading = useLoadingDelay();
|
||||
|
||||
useEffect((): void => {
|
||||
const sortedAccounts = sortAccounts(allAccounts, favorites);
|
||||
@ -234,12 +235,12 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
|
||||
/>
|
||||
</Button.Group>
|
||||
<Table
|
||||
empty={t<string>("You don't have any accounts. Some features are currently hidden and will only become available once you have accounts.")}
|
||||
empty={!isLoading && sortedAccountsWithDelegation && t<string>("You don't have any accounts. Some features are currently hidden and will only become available once you have accounts.")}
|
||||
filter={filter}
|
||||
footer={footer}
|
||||
header={header}
|
||||
>
|
||||
{sortedAccountsWithDelegation.map(({ account, delegation, isFavorite }, index): React.ReactNode => (
|
||||
{isLoading ? undefined : sortedAccountsWithDelegation?.map(({ account, delegation, isFavorite }, index): React.ReactNode => (
|
||||
<Account
|
||||
account={account}
|
||||
delegation={delegation}
|
||||
|
||||
@ -7,7 +7,7 @@ import { ComponentProps as Props } from '../types';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Button, Input, Table } from '@polkadot/react-components';
|
||||
import { useAddresses, useFavorites, useToggle } from '@polkadot/react-hooks';
|
||||
import { useAddresses, useFavorites, useLoadingDelay, useToggle } from '@polkadot/react-hooks';
|
||||
|
||||
import CreateModal from './modals/Create';
|
||||
import Address from './Address';
|
||||
@ -22,8 +22,9 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
|
||||
const { allAddresses } = useAddresses();
|
||||
const [isCreateOpen, toggleCreate] = useToggle(false);
|
||||
const [favorites, toggleFavorite] = useFavorites(STORE_FAVS);
|
||||
const [sortedAddresses, setSortedAddresses] = useState<SortedAddress[]>([]);
|
||||
const [sortedAddresses, setSortedAddresses] = useState<SortedAddress[] | undefined>();
|
||||
const [filterOn, setFilter] = useState<string>('');
|
||||
const isLoading = useLoadingDelay();
|
||||
|
||||
useEffect((): void => {
|
||||
setSortedAddresses(
|
||||
@ -76,11 +77,11 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
|
||||
/>
|
||||
)}
|
||||
<Table
|
||||
empty={t<string>('no addresses saved yet, add any existing address')}
|
||||
empty={!isLoading && sortedAddresses && t<string>('no addresses saved yet, add any existing address')}
|
||||
filter={filter}
|
||||
header={header}
|
||||
>
|
||||
{sortedAddresses.map(({ address, isFavorite }): React.ReactNode => (
|
||||
{isLoading ? undefined : sortedAddresses?.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Address
|
||||
address={address}
|
||||
filter={filterOn}
|
||||
|
||||
@ -8,7 +8,7 @@ import { Authors } from '@polkadot/react-query/BlockAuthors';
|
||||
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall, useLoadingDelay } from '@polkadot/react-hooks';
|
||||
import { BlockAuthorsContext } from '@polkadot/react-query';
|
||||
import { Option, StorageKey } from '@polkadot/types';
|
||||
|
||||
@ -101,6 +101,9 @@ function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOvervi
|
||||
const [nominatedBy, setNominatedBy] = useState<Record<string, [string, number][]> | null>();
|
||||
const [withIdentity, setWithIdentity] = useState(false);
|
||||
|
||||
// we have a very large list, so we use a loading delay
|
||||
const isLoading = useLoadingDelay();
|
||||
|
||||
useEffect((): void => {
|
||||
stakingOverview && setFiltered(
|
||||
getFiltered(stakingOverview, favorites, next)
|
||||
@ -156,7 +159,7 @@ function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOvervi
|
||||
return isIntentions
|
||||
? (
|
||||
<Table
|
||||
empty={waiting && t<string>('No waiting validators found')}
|
||||
empty={!isLoading && waiting && t<string>('No waiting validators found')}
|
||||
filter={
|
||||
<Filtering
|
||||
nameFilter={nameFilter}
|
||||
@ -167,12 +170,12 @@ function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOvervi
|
||||
}
|
||||
header={headerWaiting}
|
||||
>
|
||||
{_renderRows(elected, false).concat(_renderRows(waiting, false))}
|
||||
{isLoading ? undefined : _renderRows(elected, false).concat(_renderRows(waiting, false))}
|
||||
</Table>
|
||||
)
|
||||
: (
|
||||
<Table
|
||||
empty={validators && t<string>('No active validators found')}
|
||||
empty={!isLoading && validators && t<string>('No active validators found')}
|
||||
filter={
|
||||
<Filtering
|
||||
nameFilter={nameFilter}
|
||||
@ -183,7 +186,7 @@ function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOvervi
|
||||
}
|
||||
header={headerActive}
|
||||
>
|
||||
{_renderRows(validators, true)}
|
||||
{isLoading ? undefined : _renderRows(validators, true)}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useDebounce } from '@polkadot/react-hooks';
|
||||
import { useDebounce, useLoadingDelay } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Input from '../Input';
|
||||
@ -28,11 +28,7 @@ function InputAddressMulti ({ available, availableLabel, className = '', default
|
||||
const [_filter, setFilter] = useState<string>('');
|
||||
const [selected, setSelected] = useState<string[]>([]);
|
||||
const filter = useDebounce(_filter);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect((): void => {
|
||||
setTimeout(() => setIsLoading(false), 250);
|
||||
});
|
||||
const isLoading = useLoadingDelay();
|
||||
|
||||
useEffect((): void => {
|
||||
defaultValue && setSelected(defaultValue);
|
||||
|
||||
@ -11,7 +11,7 @@ import Spinner from '../Spinner';
|
||||
interface Props {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
empty?: React.ReactNode;
|
||||
empty?: React.ReactNode | false;
|
||||
emptySpinner?: React.ReactNode;
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import Head from './Head';
|
||||
interface TableProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
empty?: React.ReactNode;
|
||||
empty?: React.ReactNode | false;
|
||||
emptySpinner?: React.ReactNode;
|
||||
filter?: React.ReactNode;
|
||||
footer?: React.ReactNode;
|
||||
|
||||
@ -18,6 +18,7 @@ export { default as useFavorites } from './useFavorites';
|
||||
export { default as useIncrement } from './useIncrement';
|
||||
export { default as useIpfs } from './useIpfs';
|
||||
export { default as useIsMountedRef } from './useIsMountedRef';
|
||||
export { default as useLoadingDelay } from './useLoadingDelay';
|
||||
export { default as useMembers } from './useMembers';
|
||||
export { default as useModal } from './useModal';
|
||||
export { default as useNonEmptyString } from './useNonEmptyString';
|
||||
|
||||
19
packages/react-hooks/src/useLoadingDelay.ts
Normal file
19
packages/react-hooks/src/useLoadingDelay.ts
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2017-2020 @polkadot/react-hooks authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import useIsMountedRef from './useIsMountedRef';
|
||||
|
||||
export default function useLoadingDelay (delay = 100): boolean {
|
||||
const mountedRef = useIsMountedRef();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect((): void => {
|
||||
setTimeout((): void => {
|
||||
mountedRef.current && setIsLoading(false);
|
||||
}, delay);
|
||||
});
|
||||
|
||||
return isLoading;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user