chore: fix update results from dataProvider when variable change (#1962)

* chore: fix race conditions in useDataProvider hook

* chore: fix race conditions in useDataProvider hook - populate fix to other modules

* chore: fix race conditions in useDataProvider hook - populate fix to other modules

* chore: fix race conditions in useDataProvider hook - populate fix to other modules

* chore: fix race conditions in useDataProvider hook - populate fix to other modules

Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
macqbat 2022-11-07 13:14:21 +01:00 committed by GitHub
parent e2b789000c
commit dc5881b71b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 102 additions and 95 deletions

View File

@ -32,10 +32,8 @@ const AccountsManager = () => {
dataProvider: aggregatedAccountsDataProvider,
update,
variables,
updateOnInit: true,
});
if (!dataRef.current && data) {
dataRef.current = data;
}
const getRows = async ({
successCallback,
startRow,

View File

@ -1,8 +1,9 @@
import { useState } from 'react';
import { useCallback, useState } from 'react';
import { Button } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers';
import { WithdrawalDialogs } from '@vegaprotocol/withdraws';
import { Web3Container } from '@vegaprotocol/web3';
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
@ -16,6 +17,23 @@ export const AccountsContainer = () => {
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const [assetId, setAssetId] = useState<string>();
const onClickAsset = useCallback(
(value?: string | AssetFieldsFragment) => {
value && openAssetDetailsDialog(value);
},
[openAssetDetailsDialog]
);
const onClickWithdraw = useCallback((assetId?: string) => {
setWithdrawDialog(true);
setAssetId(assetId);
}, []);
const onClickDeposit = useCallback((assetId?: string) => {
setDepositDialog(true);
setAssetId(assetId);
}, []);
if (!pubKey) {
return (
<Splash>
@ -30,17 +48,9 @@ export const AccountsContainer = () => {
<div>
<AccountManager
partyId={pubKey}
onClickAsset={(value) => {
value && openAssetDetailsDialog(value);
}}
onClickWithdraw={(assetId) => {
setWithdrawDialog(true);
setAssetId(assetId);
}}
onClickDeposit={(assetId) => {
setDepositDialog(true);
setAssetId(assetId);
}}
onClickAsset={onClickAsset}
onClickWithdraw={onClickWithdraw}
onClickDeposit={onClickDeposit}
/>
</div>
<div className="flex justify-end p-2 px-[11px]">

View File

@ -24,7 +24,7 @@ const Portfolio = () => {
const wrapperClasses = 'h-full max-h-full flex flex-col';
return (
<div className={wrapperClasses}>
<ResizableGrid vertical={true}>
<ResizableGrid vertical>
<ResizableGridPanel minSize={75}>
<PortfolioGridChild>
<Tabs>

View File

@ -1,12 +1,11 @@
import { act, render } from '@testing-library/react';
import { AccountManager } from './accounts-manager';
import * as helpers from '@vegaprotocol/react-helpers';
const mockReload = jest.fn();
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useDataProvider: jest.fn(() => ({
data: [],
reload: mockReload,
})),
}));
@ -15,10 +14,14 @@ describe('AccountManager', () => {
const { rerender } = render(
<AccountManager partyId="partyOne" onClickAsset={jest.fn} />
);
expect(mockReload).not.toHaveBeenCalled();
expect(
(helpers.useDataProvider as jest.Mock).mock.calls[0][0].variables.partyId
).toEqual('partyOne');
await act(() => {
rerender(<AccountManager partyId="partyTwo" onClickAsset={jest.fn} />);
});
expect(mockReload).toHaveBeenCalledWith(true);
expect(
(helpers.useDataProvider as jest.Mock).mock.calls[1][0].variables.partyId
).toEqual('partyTwo');
});
});

View File

@ -2,7 +2,7 @@ import type { Asset } from '@vegaprotocol/assets';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { useRef, useMemo, useCallback } from 'react';
import { useRef, useMemo, useCallback, memo } from 'react';
import type { AccountFields } from './accounts-data-provider';
import { aggregatedAccountsDataProvider } from './accounts-data-provider';
import type { GetRowsParams } from './accounts-table';
@ -15,13 +15,13 @@ interface AccountManagerProps {
onClickDeposit?: (assetId?: string) => void;
}
export const AccountManager = ({
export const AccountManager = memo(
({
onClickAsset,
onClickWithdraw,
onClickDeposit,
partyId,
}: AccountManagerProps) => {
const partyIdRef = useRef<string>(partyId);
}: AccountManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const dataRef = useRef<AccountFields[] | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
@ -34,21 +34,12 @@ export const AccountManager = ({
[gridRef]
);
const { data, loading, error, reload } = useDataProvider<
AccountFields[],
never
>({
const { data, loading, error } = useDataProvider<AccountFields[], never>({
dataProvider: aggregatedAccountsDataProvider,
update,
variables,
updateOnInit: true,
});
if (partyId !== partyIdRef.current) {
reload(true);
partyIdRef.current = partyId;
}
if (!dataRef.current && data) {
dataRef.current = data;
}
const getRows = async ({
successCallback,
startRow,
@ -73,6 +64,7 @@ export const AccountManager = ({
/>
</AsyncRenderer>
);
};
}
);
export default AccountManager;
export default memo(AccountManager);

View File

@ -86,8 +86,9 @@ describe('useFillsList Hook', () => {
addNewRows: expect.any(Function),
getRows: expect.any(Function),
});
updateMock({ data: mockData });
expect(mockRefreshAgGridApi).not.toHaveBeenCalled();
updateMock({ data: {} });
updateMock({ data: mockData });
expect(mockRefreshAgGridApi).toHaveBeenCalled();
});
});

View File

@ -77,11 +77,14 @@ export const useFillsList = ({ partyId, gridRef, scrolledToTop }: Props) => {
const { data, error, loading, load, totalCount } = useDataProvider<
(TradeEdge | null)[],
Trade[]
>({ dataProvider: fillsWithMarketProvider, update, insert, variables });
if (!dataRef.current && data) {
>({
dataProvider: fillsWithMarketProvider,
update,
insert,
variables,
updateOnInit: true,
});
totalCountRef.current = totalCount;
dataRef.current = data;
}
const getRows = makeInfiniteScrollGetRows<TradeEdge>(
newRows,

View File

@ -8,7 +8,7 @@ import type { IGetRowsParams } from 'ag-grid-community';
const loadMock = jest.fn();
let mockData = null;
let mockData: Edge<OrderFieldsFragment>[] | null = null;
let mockDataProviderData = {
data: mockData as (Edge<OrderFieldsFragment> | null)[] | null,
error: undefined,
@ -94,8 +94,9 @@ describe('useOrderListData Hook', () => {
addNewRows: expect.any(Function),
getRows: expect.any(Function),
});
updateMock({ data: mockData, delta: [] });
expect(mockRefreshAgGridApi).not.toHaveBeenCalled();
updateMock({ data: [], delta: [] });
updateMock({ data: mockData, delta: [] });
expect(mockRefreshAgGridApi).toHaveBeenCalled();
});
@ -148,6 +149,10 @@ describe('useOrderListData Hook', () => {
endRow: 4,
} as unknown as IGetRowsParams;
await waitFor(async () => {
updateMock({ data: mockData });
});
await waitFor(async () => {
const promise = result.current.getRows(getRowsParams);
updateMock({ data: mockNextData, delta: mockDelta });

View File

@ -77,11 +77,9 @@ export const useOrderListData = ({
update,
insert,
variables,
updateOnInit: true,
});
if (!dataRef.current && data) {
totalCountRef.current = totalCount;
dataRef.current = data;
}
const getRows = makeInfiniteScrollGetRows<OrderEdge>(
newRows,

View File

@ -85,12 +85,9 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
update,
insert,
variables,
updateOnInit: true,
});
totalCountRef.current = totalCount;
if (!dataRef.current && data) {
dataRef.current = data;
}
const getRows = makeInfiniteScrollGetRows<TradeEdge>(
newRows,
dataRef,