Skip to content

Commit

Permalink
fix: Render safe guards, pool useEffect fixes (#1906)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ross Bulat committed Jan 27, 2024
1 parent f6c0b93 commit 7c0212f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 27 deletions.
33 changes: 27 additions & 6 deletions src/contexts/Connect/ImportedAccounts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import type { ReactNode } from 'react';
import { createContext, useCallback, useContext } from 'react';
import type { MaybeAddress } from 'types';
import type { ExternalAccount } from '@polkadot-cloud/react/types';
import type {
ExternalAccount,
ImportedAccount,
} from '@polkadot-cloud/react/types';
import { ManualSigners } from 'consts';
import {
useEffectIgnoreInitial,
Expand Down Expand Up @@ -33,13 +36,31 @@ export const ImportedAccountsProvider = ({
const { extensionAccounts } = useExtensionAccounts();
const allAccounts = extensionAccounts.concat(otherAccounts);

// Stringify account addresses and account names to determine if they have changed. Ignore other properties including `signer` and `source`.
const shallowAccountStringify = (accounts: ImportedAccount[]) => {
const sorted = accounts.sort((a, b) => {
if (a.address < b.address) {
return -1;
}
if (a.address > b.address) {
return 1;
}
return 0;
});
return JSON.stringify(
sorted.map((account) => [account.address, account.name])
);
};

const allAccountsStringified = shallowAccountStringify(allAccounts);

// Gets an account from `allAccounts`.
//
// Caches the function when imported accounts update.
const getAccount = useCallback(
(who: MaybeAddress) =>
allAccounts.find(({ address }) => address === who) || null,
[allAccounts]
[allAccountsStringified]
);

// Checks if an address is a read-only account.
Expand All @@ -54,7 +75,7 @@ export const ImportedAccountsProvider = ({
}
return false;
},
[allAccounts]
[allAccountsStringified]
);

// Checks whether an account can sign transactions.
Expand All @@ -66,7 +87,7 @@ export const ImportedAccountsProvider = ({
(account) =>
account.address === address && account.source !== 'external'
) !== undefined,
[allAccounts]
[allAccountsStringified]
);

// Checks whether an account needs manual signing.
Expand All @@ -80,15 +101,15 @@ export const ImportedAccountsProvider = ({
allAccounts.find(
(a) => a.address === address && ManualSigners.includes(a.source)
) !== undefined,
[allAccounts]
[allAccountsStringified]
);

// Keep accounts in sync with `BalancesController`.
useEffectIgnoreInitial(() => {
if (isReady) {
BalancesController.syncAccounts(allAccounts.map((a) => a.address));
}
}, [isReady, allAccounts]);
}, [isReady, allAccountsStringified]);

return (
<ImportedAccountsContext.Provider
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/Pools/ActivePools/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ export const ActivePoolsProvider = ({ children }: { children: ReactNode }) => {
setStateWithRef('syncing', setSynced, syncedRef);
handlePoolSubscriptions();
}
}, [network, isReady, syncedRef.current]);
}, [network, isReady, synced]);

// re-calculate pending rewards when membership changes
useEffectIgnoreInitial(() => {
Expand Down
53 changes: 33 additions & 20 deletions src/contexts/Pools/PoolMemberships/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const PoolMembershipsProvider = ({
const { t } = useTranslation('base');
const { network } = useNetwork();
const { api, isReady } = useApi();
const { accounts } = useImportedAccounts();
const { activeAccount } = useActiveAccounts();
const { accounts: connectAccounts } = useImportedAccounts();

// Stores pool memberships for the imported accounts.
const [poolMemberships, setPoolMemberships] = useState<PoolMembership[]>([]);
Expand All @@ -44,31 +44,13 @@ export const PoolMembershipsProvider = ({
// Stores pool membership unsubs.
const unsubs = useRef<AnyApi[]>([]);

useEffectIgnoreInitial(() => {
if (isReady) {
(() => {
setStateWithRef([], setPoolMemberships, poolMembershipsRef);
unsubAll();
getPoolMemberships();
})();
}
}, [network, isReady, connectAccounts]);

// subscribe to account pool memberships
const getPoolMemberships = async () => {
Promise.all(
connectAccounts.map(({ address }) => subscribeToPoolMembership(address))
accounts.map(({ address }) => subscribeToPoolMembership(address))
);
};

// unsubscribe from pool memberships on unmount
useEffect(
() => () => {
unsubAll();
},
[]
);

// unsubscribe from all pool memberships
const unsubAll = () => {
Object.values(unsubs.current).forEach((v: Fn) => v());
Expand Down Expand Up @@ -183,6 +165,37 @@ export const PoolMembershipsProvider = ({
},
];

// Reset and re-sync pool memberships on network change.
// re-sync pool memberships when accounts update.
useEffectIgnoreInitial(() => {
if (isReady) {
(() => {
// NOTE: resetting memberships here.
setStateWithRef([], setPoolMemberships, poolMembershipsRef);
unsubAll();
getPoolMemberships();
})();
}
}, [network, isReady]);

// re-sync pool memberships when accounts update.
useEffectIgnoreInitial(() => {
if (isReady) {
(() => {
unsubAll();
getPoolMemberships();
})();
}
}, [isReady, accounts]);

// Unsubscribe from pool memberships on unmount.
useEffect(
() => () => {
unsubAll();
},
[]
);

return (
<PoolMembershipsContext.Provider
value={{
Expand Down

0 comments on commit 7c0212f

Please sign in to comment.