Merge prev/current bags stash info (& React.memo) (#7267)
* Merge prev/current bags stash info (& React.memo) * Adjust * Adjust loading
This commit is contained in:
parent
cc56f65179
commit
e182d20853
@ -2,13 +2,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { u64 } from '@polkadot/types';
|
||||
import type { AccountId32 } from '@polkadot/types/interfaces';
|
||||
import type { PalletBagsListListBag } from '@polkadot/types/lookup';
|
||||
import type { StashNode } from './types';
|
||||
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { AddressMini, Spinner } from '@polkadot/react-components';
|
||||
import { useIncrement } from '@polkadot/react-hooks';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -22,27 +22,24 @@ interface Props {
|
||||
stashNodes?: StashNode[];
|
||||
}
|
||||
|
||||
export default function Bag ({ id, info, stashNodes }: Props): React.ReactElement<Props> {
|
||||
function Bag ({ id, info, stashNodes }: Props): React.ReactElement<Props> {
|
||||
const [[headId, trigger], setHeadId] = useState<[AccountId32 | null, number]>([null, 0]);
|
||||
const [isLoading, setLoading] = useState(true);
|
||||
const [trigger, doRefresh] = useIncrement(1);
|
||||
const headId = useMemo(
|
||||
() => stashNodes && stashNodes.length
|
||||
? info.head.unwrapOr(null)
|
||||
: null,
|
||||
[info, stashNodes]
|
||||
);
|
||||
const list = useBagEntries(headId, trigger);
|
||||
const [isCompleted, list] = useBagEntries(headId, trigger);
|
||||
const bonded = useBonded(list);
|
||||
|
||||
useEffect((): void => {
|
||||
info && stashNodes &&
|
||||
setHeadId(([, trigger]) => [info.head.unwrapOr(null), ++trigger]);
|
||||
}, [info, stashNodes]);
|
||||
|
||||
useEffect((): void => {
|
||||
setLoading(
|
||||
stashNodes && stashNodes.length
|
||||
? list
|
||||
? !bonded
|
||||
: true
|
||||
? !isCompleted || !bonded
|
||||
: false
|
||||
);
|
||||
}, [bonded, list, stashNodes]);
|
||||
}, [bonded, isCompleted, stashNodes]);
|
||||
|
||||
return (
|
||||
<tr>
|
||||
@ -52,7 +49,6 @@ export default function Bag ({ id, info, stashNodes }: Props): React.ReactElemen
|
||||
<td className='address'>
|
||||
{stashNodes?.map(({ stashId }) => (
|
||||
<Stash
|
||||
doRefresh={doRefresh}
|
||||
isLoading={isLoading}
|
||||
key={stashId}
|
||||
list={bonded}
|
||||
@ -71,3 +67,5 @@ export default function Bag ({ id, info, stashNodes }: Props): React.ReactElemen
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Bag);
|
||||
|
||||
@ -13,7 +13,6 @@ import { useTranslation } from '../translate';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
doRefresh: () => void;
|
||||
isLoading: boolean;
|
||||
list?: ListNode[];
|
||||
stashId: string;
|
||||
@ -26,7 +25,7 @@ function findEntry (stashId: string, list: ListNode[] = []): [ListNode | null, b
|
||||
return [entry, !!other, entry && other ? entry.index - other.index : 0];
|
||||
}
|
||||
|
||||
function Stash ({ className, doRefresh, isLoading, list, stashId }: Props): React.ReactElement<Props> {
|
||||
function Stash ({ className, isLoading, list, stashId }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const [stashInfo, canJump, jumpCount] = useMemo(
|
||||
@ -45,7 +44,6 @@ function Stash ({ className, doRefresh, isLoading, list, stashId }: Props): Reac
|
||||
icon='caret-up'
|
||||
isDisabled={!canJump || isLoading}
|
||||
label={t<string>('Move up {{jumpCount}}', { replace: { jumpCount } })}
|
||||
onSuccess={doRefresh}
|
||||
params={[stashInfo?.jump]}
|
||||
tx={api.tx.bagsList.putInFrontOf}
|
||||
/>
|
||||
@ -53,7 +51,7 @@ function Stash ({ className, doRefresh, isLoading, list, stashId }: Props): Reac
|
||||
);
|
||||
}
|
||||
|
||||
export default styled(Stash)`
|
||||
export default React.memo(styled(Stash)`
|
||||
.ui--AddressMini {
|
||||
vertical-align: middle;
|
||||
}
|
||||
@ -62,4 +60,4 @@ export default styled(Stash)`
|
||||
cursor: default;
|
||||
opacity: 0;
|
||||
}
|
||||
`;
|
||||
`);
|
||||
|
||||
@ -15,7 +15,7 @@ interface Props {
|
||||
ids?: u64[];
|
||||
}
|
||||
|
||||
export default function Summary ({ className = '', ids }: Props): React.ReactElement<Props> {
|
||||
function Summary ({ className = '', ids }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@ -29,3 +29,5 @@ export default function Summary ({ className = '', ids }: Props): React.ReactEle
|
||||
</SummaryBox>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Summary);
|
||||
|
||||
@ -18,7 +18,7 @@ interface Props {
|
||||
ownStashes?: StakerState[];
|
||||
}
|
||||
|
||||
export default function Bags ({ ownStashes }: Props): React.ReactElement<Props> {
|
||||
function Bags ({ ownStashes }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const ids = useBagsIds();
|
||||
const list = useBagsList(ids);
|
||||
@ -39,7 +39,7 @@ export default function Bags ({ ownStashes }: Props): React.ReactElement<Props>
|
||||
]);
|
||||
|
||||
const sorted = useMemo(
|
||||
() => list
|
||||
() => list && nodes
|
||||
? [...list].sort((a, b) =>
|
||||
nodes[a[0]]
|
||||
? nodes[b[0]]
|
||||
@ -57,7 +57,7 @@ export default function Bags ({ ownStashes }: Props): React.ReactElement<Props>
|
||||
<>
|
||||
<Summary ids={ids} />
|
||||
<Table
|
||||
empty={list && list.length === 0 && t<string>('No available bags')}
|
||||
empty={nodes && list && list.length === 0 && t<string>('No available bags')}
|
||||
emptySpinner={t<string>('Retrieving all available bags, this will take some time')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
@ -73,3 +73,5 @@ export default function Bags ({ ownStashes }: Props): React.ReactElement<Props>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Bags);
|
||||
|
||||
@ -17,7 +17,7 @@ interface Result {
|
||||
const EMPTY: [AccountId32 | null, Result] = [null, { isCompleted: false, list: [] }];
|
||||
const EMPTY_LIST: AccountId32[] = [];
|
||||
|
||||
function useBagEntriesImpl (headId: AccountId32 | null, trigger: number): AccountId32[] {
|
||||
function useBagEntriesImpl (headId: AccountId32 | null, trigger: number): [boolean, AccountId32[]] {
|
||||
const { api } = useApi();
|
||||
const [[currId, { isCompleted, list }], setCurrent] = useState<[AccountId32 | null, Result]>(EMPTY);
|
||||
const node = useCall<Option<PalletBagsListListNode>>(!!currId && api.query.bagsList.listNodes, [currId]);
|
||||
@ -45,9 +45,12 @@ function useBagEntriesImpl (headId: AccountId32 | null, trigger: number): Accoun
|
||||
}
|
||||
}, [node]);
|
||||
|
||||
return isCompleted
|
||||
? list
|
||||
: EMPTY_LIST;
|
||||
return [
|
||||
isCompleted,
|
||||
isCompleted
|
||||
? list
|
||||
: EMPTY_LIST
|
||||
];
|
||||
}
|
||||
|
||||
export default createNamedHook('useBagEntries', useBagEntriesImpl);
|
||||
|
||||
@ -5,12 +5,13 @@ import type { Option } from '@polkadot/types';
|
||||
import type { PalletBagsListListNode } from '@polkadot/types/lookup';
|
||||
import type { StashNode } from './types';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
type Result = Record<string, StashNode[]>;
|
||||
|
||||
const multiOptions = {
|
||||
defaultValue: {} as Result,
|
||||
transform: (opts: Option<PalletBagsListListNode>[]): Result =>
|
||||
opts
|
||||
.filter((o) => o.isSome)
|
||||
@ -28,10 +29,28 @@ const multiOptions = {
|
||||
}, {})
|
||||
};
|
||||
|
||||
function merge (prev: Result, curr: Result): Result {
|
||||
return Object
|
||||
.entries(curr)
|
||||
.reduce((all: Result, [id, nodes]): Result => {
|
||||
all[id] = prev[id] && JSON.stringify(nodes) === JSON.stringify(prev[id])
|
||||
? prev[id]
|
||||
: nodes;
|
||||
|
||||
return all;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function useBagsNodesImpl (stashIds: string[]): Result {
|
||||
const { api } = useApi();
|
||||
const [result, setResult] = useState<Result>({});
|
||||
const query = useCall(stashIds && stashIds.length !== 0 && api.query.bagsList.listNodes.multi, [stashIds], multiOptions);
|
||||
|
||||
return useCall(stashIds && stashIds.length !== 0 && api.query.bagsList.listNodes.multi, [stashIds], multiOptions) as Result;
|
||||
useEffect((): void => {
|
||||
query && setResult((prev) => merge(prev, query));
|
||||
}, [query]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default createNamedHook('useBagsNodes', useBagsNodesImpl);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user