diff --git a/packages/page-parachains/src/Overview/Parachain.tsx b/packages/page-parachains/src/Overview/Parachain.tsx index fcdcdb337c..2bb557d463 100644 --- a/packages/page-parachains/src/Overview/Parachain.tsx +++ b/packages/page-parachains/src/Overview/Parachain.tsx @@ -39,7 +39,7 @@ const transformLast = { transform: (header: Header) => header.number.unwrap() }; -const transformMulti = { +const optionsMulti = { defaultValue: { headHex: null, qDmp: 0, @@ -76,7 +76,7 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastInclusion [api.query.hrmp.hrmpEgressChannelsIndex, id], [api.query.hrmp.hrmpIngressChannelsIndex, id], [api.query.hrmp.hrmpWatermarks, id] - ], transformMulti) as QueryState; // we have a default value, cast is safe + ], optionsMulti); const blockDelay = useMemo( () => bestNumber && ( diff --git a/packages/page-parachains/src/Proposals/useProposals.ts b/packages/page-parachains/src/Proposals/useProposals.ts index 4fa913887d..4f01bde09e 100644 --- a/packages/page-parachains/src/Proposals/useProposals.ts +++ b/packages/page-parachains/src/Proposals/useProposals.ts @@ -7,7 +7,9 @@ import type { ProposalExt, Proposals, ScheduledProposals } from '../types'; import { useEffect, useMemo, useState } from 'react'; -import { useApi, useCall, useIsMountedRef } from '@polkadot/react-hooks'; +import { useApi, useCall, useCallMulti, useIsMountedRef } from '@polkadot/react-hooks'; + +type MultiQuery = [EventRecord[], SessionIndex | undefined, ParaId[] | undefined]; function createResult (sessionIndex: SessionIndex, approvedIds: ParaId[], proposalKeys: { args: [ParaId] }[], scheduledProposals: [{ args: [SessionIndex] }, ParaId[]][]): Proposals { return { @@ -22,19 +24,30 @@ function createResult (sessionIndex: SessionIndex, approvedIds: ParaId[], propos }; } +const optionsMulti = { + defaultValue: [[], undefined, undefined] as MultiQuery, + transform: ([records, sessionIndex, approvedIds]: [EventRecord[], SessionIndex, ParaId[] | undefined]): MultiQuery => [ + records.filter(({ event, phase }) => phase?.isApplyExtrinsic && event?.section === 'proposeParachain'), + sessionIndex, + approvedIds + ] +}; + export default function useProposals (): Proposals | undefined { const { api } = useApi(); const mountedRef = useIsMountedRef(); const [state, setState] = useState(); const [trigger, setTrigger] = useState(Date.now()); - const sessionIndex = useCall(api.query.session.currentIndex); - const approvedIds = useCall(api.query.proposeParachain?.approvedProposals); - const events = useCall(api.query.system.events); + const [events, sessionIndex, approvedIds] = useCallMulti([ + api.query.system.events, + api.query.session.currentIndex, + api.query.proposeParachain?.approvedProposals + ], optionsMulti); // trigger on any proposeParachain events useEffect((): void => { mountedRef.current && events && setTrigger((trigger) => - events.filter((r) => r && r.phase?.isApplyExtrinsic && r.event?.section === 'proposeParachain').length + events.length ? Date.now() : trigger ); diff --git a/packages/react-hooks/src/useCallMulti.ts b/packages/react-hooks/src/useCallMulti.ts index 7003e0e414..a8d31a7ef0 100644 --- a/packages/react-hooks/src/useCallMulti.ts +++ b/packages/react-hooks/src/useCallMulti.ts @@ -27,15 +27,22 @@ function subscribe (api: ApiPromise, mountedRef: MountedRef, tracker: Tracke setTimeout((): void => { if (mountedRef.current) { - if (calls.length) { - // swap to acive mode + const included = calls.map((c) => !!c); + const filtered = calls.filter((_, index) => included[index]); + + if (filtered.length) { + // swap to active mode tracker.current.isActive = true; - tracker.current.subscriber = api.queryMulti(calls, (value): void => { + tracker.current.subscriber = api.queryMulti(filtered, (value): void => { // we use the isActive flag here since .subscriber may not be set on immediate callback) if (mountedRef.current && tracker.current.isActive) { + let valueIndex = -1; + mountedRef.current && tracker.current.isActive && setValue( - transform(value) + transform( + calls.map((_, index) => included[index] ? value[++valueIndex] : undefined) + ) ); } }); @@ -47,11 +54,11 @@ function subscribe (api: ApiPromise, mountedRef: MountedRef, tracker: Tracke } // very much copied from useCall -export function useCallMulti (calls?: QueryableStorageMultiArg<'promise'>[] | null | false, options?: CallOptions): T | undefined { +export function useCallMulti (calls?: QueryableStorageMultiArg<'promise'>[] | null | false, options?: CallOptions): T { const { api } = useApi(); const mountedRef = useIsMountedRef(); const tracker = useRef({ isActive: false, serialized: null, subscriber: null }); - const [value, setValue] = useState((options || {}).defaultValue); + const [value, setValue] = useState((options || {}).defaultValue || [] as unknown as T); // initial effect, we need an un-subscription useEffect((): () => void => {